This is the mail archive of the cgen@sources.redhat.com mailing list for the CGEN project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

tabling constant-field-beyond-base patch


Finishing up the remaining bits of this patch are proving difficult.
[N.B. The issues aren't of a technical nature.]
So I'm tabling the current state of the patch here.

I hope to have the difficulties resolved RSN.  Sigh.

Index: opcodes/cgen-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/cgen-dis.c,v
retrieving revision 1.7
diff -u -p -r1.7 cgen-dis.c
--- opcodes/cgen-dis.c	10 Feb 2002 19:03:14 -0000	1.7
+++ opcodes/cgen-dis.c	6 Aug 2003 17:42:59 -0000
@@ -127,7 +127,7 @@ hash_insn_array (cd, insns, count, entsi
       value = CGEN_INSN_BASE_VALUE (insn);
       bfd_put_bits ((bfd_vma) value,
 		    buf,
-		    CGEN_INSN_MASK_BITSIZE (insn),
+		    CGEN_INSN_BASE_MASK_LENGTH (insn),
 		    big_p);
       hash = (* cd->dis_hash) (buf, value);
       add_insn_to_hash_chain (hentbuf, insn, htable, hash);
@@ -165,7 +165,7 @@ hash_insn_list (cd, insns, htable, hentb
       value = CGEN_INSN_BASE_VALUE (ilist->insn);
       bfd_put_bits((bfd_vma) value,
 		   buf,
-		   CGEN_INSN_MASK_BITSIZE (ilist->insn),
+		   CGEN_INSN_BASE_MASK_LENGTH (ilist->insn),
 		   big_p);
       hash = (* cd->dis_hash) (buf, value);
       add_insn_to_hash_chain (hentbuf, ilist->insn, htable, hash);
Index: opcodes/cgen-dis.in
===================================================================
RCS file: /cvs/src/src/opcodes/cgen-dis.in,v
retrieving revision 1.16
diff -u -p -r1.16 cgen-dis.in
--- opcodes/cgen-dis.in	2 Dec 2002 21:58:18 -0000	1.16
+++ opcodes/cgen-dis.in	6 Aug 2003 17:43:00 -0000
@@ -27,6 +27,7 @@ along with this program; if not, write t
    Keep that in mind.  */
 
 #include "sysdep.h"
+#include <assert.h>
 #include <stdio.h>
 #include "ansidecl.h"
 #include "dis-asm.h"
@@ -53,9 +54,6 @@ static int print_insn
      PARAMS ((CGEN_CPU_DESC, bfd_vma,  disassemble_info *, char *, unsigned));
 static int default_print_insn
      PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
-static int read_insn
-     PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, int,
-	      CGEN_EXTRACT_INFO *, unsigned long *));
 
 /* -- disassembler routines inserted here */
 
@@ -174,40 +172,13 @@ print_insn_normal (cd, dis_info, insn, f
     }
 }
 
-/* Subroutine of print_insn. Reads an insn into the given buffers and updates
-   the extract info.
-   Returns 0 if all is well, non-zero otherwise.  */
-
-static int
-read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
-     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
-     bfd_vma pc;
-     disassemble_info *info;
-     char *buf;
-     int buflen;
-     CGEN_EXTRACT_INFO *ex_info;
-     unsigned long *insn_value;
-{
-  int status = (*info->read_memory_func) (pc, buf, buflen, info);
-  if (status != 0)
-    {
-      (*info->memory_error_func) (status, pc, info);
-      return -1;
-    }
-
-  ex_info->dis_info = info;
-  ex_info->valid = (1 << buflen) - 1;
-  ex_info->insn_bytes = buf;
-
-  *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
-  return 0;
-}
-
 /* Utility to print an insn.
    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
    The result is the size of the insn in bytes or zero for an unknown insn
    or -1 if an error occurs fetching data (memory_error_func will have
-   been called).  */
+   been called).
+   NOTE: BUF is guaranteed to be large enough to hold the largest insn.
+   We may use it to fetch the rest of the insn as necessary.  */
 
 static int
 print_insn (cd, pc, info, buf, buflen)
@@ -217,20 +188,15 @@ print_insn (cd, pc, info, buf, buflen)
      char *buf;
      unsigned int buflen;
 {
-  CGEN_INSN_INT insn_value;
   const CGEN_INSN_LIST *insn_list;
   CGEN_EXTRACT_INFO ex_info;
-  int basesize;
+  CGEN_INSN_INT base_insn_value;
 
   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
-  basesize = cd->base_insn_bitsize < buflen * 8 ?
-                                     cd->base_insn_bitsize : buflen * 8;
-  insn_value = cgen_get_insn_value (cd, buf, basesize);
-
+  assert (cd->base_insn_bitsize == buflen * 8);
+  base_insn_value = cgen_get_insn_value (cd, buf, cd->base_insn_bitsize);
 
-  /* Fill in ex_info fields like read_insn would.  Don't actually call
-     read_insn, since the incoming buffer is already read (and possibly
-     modified a la m32r).  */
+  /* Fill in ex_info fields in preparation for reading more of the insn.  */
   ex_info.valid = (1 << buflen) - 1;
   ex_info.dis_info = info;
   ex_info.insn_bytes = buf;
@@ -238,74 +204,100 @@ print_insn (cd, pc, info, buf, buflen)
   /* The instructions are stored in hash lists.
      Pick the first one and keep trying until we find the right one.  */
 
-  insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
-  while (insn_list != NULL)
+  for (insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, base_insn_value);
+       insn_list != NULL;
+       insn_list = CGEN_DIS_NEXT_INSN (insn_list))
     {
       const CGEN_INSN *insn = insn_list->insn;
+      const CGEN_IFMT *ifmt = CGEN_OPCODE_FORMAT (CGEN_INSN_OPCODE (insn));
       CGEN_FIELDS fields;
+      CGEN_INSN_INT insn_value;
       int length;
-      unsigned long insn_value_cropped;
+      unsigned i,offset;
 
 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
       /* Not needed as insn shouldn't be in hash lists if not supported.  */
       /* Supported by this cpu?  */
       if (! @arch@_cgen_insn_supported (cd, insn))
-        {
-          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
-	  continue;
-        }
+	continue;
 #endif
 
-      /* Basic bit mask must be correct.  */
+      /* Early exit if constant bits in base value don't match.  */
+      if ((base_insn_value & CGEN_INSN_BASE_MASK (insn))
+	  != CGEN_INSN_BASE_VALUE (insn))
+	continue;
+
+      /* Read in and scan each of the remaining insn words that have constant
+	 bits, verifying the constant parts match.
+	 To handle the case where we're up against a section boundary that
+	 we potentially can read past, we don't over fetch; we only fetch
+	 what we need.  ??? This will probably require sorting insns in the
+	 hash list by increasing size.  */
       /* ??? May wish to allow target to defer this check until the extract
 	 handler.  */
 
-      /* Base size may exceed this instruction's size.  Extract the
-         relevant part from the buffer. */
-      if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
-	  (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
-	insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), 
-					   info->endian == BFD_ENDIAN_BIG);
-      else
-	insn_value_cropped = insn_value;
+      assert (cd->base_insn_bitsize == CGEN_IFMT_WORD_LENGTH (ifmt, 0));
+      offset = CGEN_IFMT_WORD_LENGTH (ifmt, 0);
+      for (i = 1; i < CGEN_INSN_NUM_WORDS (insn); ++i)
+	{
+	  /* NOTE: "words" is a misnomer but I can't think of a better one.
+	     Example: An insn with a 16 bit opcode and a 32 bit immediate has
+	     insn words of sizes 16 and 32 bits.  */
+	  unsigned word_mask = CGEN_IFMT_MASK (ifmt, i);
+	  unsigned word_length = CGEN_IFMT_WORD_LENGTH (ifmt, i);
+	  CGEN_INSN_INT word;
+
+	  /* Skip if no constant bits.  */
+	  if (word_mask == 0)
+	    continue;
+
+	  if (cgen_fill_opcode_cache (cd, &ex_info, offset / 8, word_length / 8, pc) == 0)
+	    return -1;
+	  word = cgen_get_insn_value (cd, buf + offset / 8, word_length);
+	  if ((word & word_mask) != CGEN_IVALUE_OPCODE (CGEN_OPCODE_IVALUE (CGEN_INSN_OPCODE (insn)), i))
+	    break;
+	  offset += word_length;
+	}
 
-      if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
-	  == CGEN_INSN_BASE_VALUE (insn))
+      /* Skip if we exited early.  */
+      if (i < CGEN_INSN_NUM_WORDS (insn))
+	continue;
+
+      /* If entire insn is recorded as an int, make sure we have the entire
+	 insn.  */
+      insn_value = base_insn_value;
+#if CGEN_INT_INSN_P
+      if (cd->base_insn_bitsize != CGEN_IFMT_LENGTH (ifmt))
 	{
-	  /* Printing is handled in two passes.  The first pass parses the
-	     machine insn and extracts the fields.  The second pass prints
-	     them.  */
-
-	  /* Make sure the entire insn is loaded into insn_value, if it
-	     can fit.  */
-	  if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
-	      (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
+	  /* We may have skipped over some words.  Fetch them now.  */
+	  for (i = 1; i < CGEN_INSN_NUM_WORDS (insn); ++i)
 	    {
-	      unsigned long full_insn_value;
-	      int rc = read_insn (cd, pc, info, buf,
-				  CGEN_INSN_BITSIZE (insn) / 8,
-				  & ex_info, & full_insn_value);
-	      if (rc != 0)
-		return rc;
-	      length = CGEN_EXTRACT_FN (cd, insn)
-		(cd, insn, &ex_info, full_insn_value, &fields, pc);
-	    }
-	  else
-	    length = CGEN_EXTRACT_FN (cd, insn)
-	      (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
-
-	  /* length < 0 -> error */
-	  if (length < 0)
-	    return length;
-	  if (length > 0)
-	    {
-	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
-	      /* length is in bits, result is in bytes */
-	      return length / 8;
+	      unsigned word_mask = CGEN_IFMT_MASK (ifmt, i);
+	      unsigned word_length = CGEN_IFMT_WORD_LENGTH (ifmt, i);
+	      if (word_mask == 0)
+		if (cgen_fill_opcode_cache (cd, &ex_info, offset / 8, word_length / 8, pc) == 0)
+		  return -1;
 	    }
+	  insn_value = cgen_get_insn_value (cd, buf, CGEN_IFMT_LENGTH (ifmt));
 	}
+#endif
 
-      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
+      /* Printing is handled in two passes.  The first pass parses the
+	 machine insn and extracts the fields.  The second pass prints
+	 them.  */
+
+      length = CGEN_EXTRACT_FN (cd, insn)
+	(cd, insn, &ex_info, insn_value, &fields, pc);
+
+      /* length < 0 -> error */
+      if (length < 0)
+	return length;
+      if (length > 0)
+	{
+	  CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
+	  /* length is in bits, result is in bytes */
+	  return length / 8;
+	}
     }
 
   return 0;
Index: opcodes/cgen-ibld.in
===================================================================
RCS file: /cvs/src/src/opcodes/cgen-ibld.in,v
retrieving revision 1.14
diff -u -p -r1.14 cgen-ibld.in
--- opcodes/cgen-ibld.in	9 Nov 2001 10:21:22 -0000	1.14
+++ opcodes/cgen-ibld.in	6 Aug 2003 17:43:00 -0000
@@ -25,6 +25,7 @@ along with this program; if not, write t
    Keep that in mind.  */
 
 #include "sysdep.h"
+#include <assert.h>
 #include <stdio.h>
 #include "ansidecl.h"
 #include "dis-asm.h"
@@ -58,16 +59,14 @@ static int extract_insn_normal
 	      CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
 #if CGEN_INT_INSN_P
 static void put_insn_int_value
-     PARAMS ((CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT));
+     PARAMS ((CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, unsigned, unsigned, unsigned,
+	      CGEN_INSN_INT));
 #endif
 #if ! CGEN_INT_INSN_P
 static CGEN_INLINE void insert_1
      PARAMS ((CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *));
-static CGEN_INLINE int fill_cache
-     PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *,  int, int, bfd_vma));
 static CGEN_INLINE long extract_1
-     PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int,
-	      unsigned char *, bfd_vma));
+     PARAMS ((CGEN_CPU_DESC, int, int, int, unsigned char *));
 #endif
 
 /* Operand insertion.  */
@@ -123,7 +122,8 @@ insert_normal (cd, value, attrs, word_of
      CGEN_CPU_DESC cd;
      long value;
      unsigned int attrs;
-     unsigned int word_offset, start, length, word_length, total_length;
+     unsigned int word_offset, start, length, word_length;
+     unsigned int total_length ATTRIBUTE_UNUSED;
      CGEN_INSN_BYTES_PTR buffer;
 {
   static char errbuf[100];
@@ -135,22 +135,11 @@ insert_normal (cd, value, attrs, word_of
     return NULL;
 
 #if 0
-  if (CGEN_INT_INSN_P
-      && word_offset != 0)
-    abort ();
+  if (CGEN_INT_INSN_P)
+    assert (word_offset == 0);
 #endif
 
-  if (word_length > 32)
-    abort ();
-
-  /* For architectures with insns smaller than the base-insn-bitsize,
-     word_length may be too big.  */
-  if (cd->min_insn_bitsize < cd->base_insn_bitsize)
-    {
-      if (word_offset == 0
-	  && word_length > total_length)
-	word_length = total_length;
-    }
+  assert (word_length <= 32);
 
   /* Ensure VALUE will fit.  */
   if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
@@ -239,29 +228,33 @@ insert_insn_normal (cd, insn, fields, bu
      CGEN_INSN_BYTES_PTR buffer;
      bfd_vma pc;
 {
+  const CGEN_IFMT *ifmt = CGEN_OPCODE_FORMAT (CGEN_INSN_OPCODE (insn));
   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
-  unsigned long value;
   const CGEN_SYNTAX_CHAR_TYPE * syn;
+  unsigned i,offset;
 
   CGEN_INIT_INSERT (cd);
-  value = CGEN_INSN_BASE_VALUE (insn);
 
-  /* If we're recording insns as numbers (rather than a string of bytes),
-     target byte order handling is deferred until later.  */
+  /* Fill in the constant bits of the insn.  */
 
-#if CGEN_INT_INSN_P
+  assert (cd->base_insn_bitsize == CGEN_IFMT_WORD_LENGTH (ifmt, 0));
+  offset = 0;
 
-  put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
-		      CGEN_FIELDS_BITSIZE (fields), value);
+  for (i = 0; i < CGEN_INSN_NUM_WORDS (insn); ++i)
+    {
+      unsigned word_length = CGEN_IFMT_WORD_LENGTH (ifmt, i);
+      CGEN_INSN_INT value = CGEN_IVALUE_OPCODE (CGEN_OPCODE_IVALUE (CGEN_INSN_OPCODE (insn)), i);
 
+#if CGEN_INT_INSN_P
+      put_insn_int_value (cd, buffer, offset, word_length,
+			  CGEN_FIELDS_BITSIZE (fields), value);
 #else
-
-  cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
-					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
-		       value);
-
+      cgen_put_insn_value (cd, buffer + offset / 8, word_length, value);
 #endif /* ! CGEN_INT_INSN_P */
 
+      offset += word_length;
+    }
+
   /* ??? It would be better to scan the format's fields.
      Still need to be able to insert a value based on the operand though;
      e.g. storing a branch displacement that got resolved later.
@@ -284,98 +277,52 @@ insert_insn_normal (cd, insn, fields, bu
 }
 
 #if CGEN_INT_INSN_P
-/* Cover function to store an insn value into an integral insn.  Must go here
- because it needs <prefix>-desc.h for CGEN_INT_INSN_P.  */
+
+/* Cover function to store an insn value into an integral insn.
+   Normally ISAs with integral insns only have one word insns.
+   However, the m32r, for example, has CGEN_INT_INSN_P with 32 bit insns
+   composed of two 16 bit "words".  */
 
 static void
-put_insn_int_value (cd, buf, length, insn_length, value)
+put_insn_int_value (cd, buf, subword_offset, subword_length, insn_length, value)
      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
      CGEN_INSN_BYTES_PTR buf;
-     int length;
-     int insn_length;
+     unsigned subword_offset;
+     unsigned subword_length;
+     unsigned insn_length;
      CGEN_INSN_INT value;
 {
-  /* For architectures with insns smaller than the base-insn-bitsize,
-     length may be too big.  */
-  if (length > insn_length)
-    *buf = value;
+  assert (subword_offset + subword_length <= insn_length);
+
+  if (subword_length == insn_length)
+    {
+      *buf = value;
+    }
   else
     {
-      int shift = insn_length - length;
+      unsigned shift = insn_length - subword_offset - subword_length;
       /* Written this way to avoid undefined behaviour.  */
-      CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
+      CGEN_INSN_INT mask = (((1L << (subword_length - 1)) - 1) << 1) | 1;
       *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
     }
 }
+
 #endif
 
 /* Operand extraction.  */
 
 #if ! CGEN_INT_INSN_P
 
-/* Subroutine of extract_normal.
-   Ensure sufficient bytes are cached in EX_INFO.
-   OFFSET is the offset in bytes from the start of the insn of the value.
-   BYTES is the length of the needed value.
-   Returns 1 for success, 0 for failure.  */
-
-static CGEN_INLINE int
-fill_cache (cd, ex_info, offset, bytes, pc)
-     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
-     CGEN_EXTRACT_INFO *ex_info;
-     int offset, bytes;
-     bfd_vma pc;
-{
-  /* It's doubtful that the middle part has already been fetched so
-     we don't optimize that case.  kiss.  */
-  unsigned int mask;
-  disassemble_info *info = (disassemble_info *) ex_info->dis_info;
-
-  /* First do a quick check.  */
-  mask = (1 << bytes) - 1;
-  if (((ex_info->valid >> offset) & mask) == mask)
-    return 1;
-
-  /* Search for the first byte we need to read.  */
-  for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
-    if (! (mask & ex_info->valid))
-      break;
-
-  if (bytes)
-    {
-      int status;
-
-      pc += offset;
-      status = (*info->read_memory_func)
-	(pc, ex_info->insn_bytes + offset, bytes, info);
-
-      if (status != 0)
-	{
-	  (*info->memory_error_func) (status, pc, info);
-	  return 0;
-	}
-
-      ex_info->valid |= ((1 << bytes) - 1) << offset;
-    }
-
-  return 1;
-}
-
 /* Subroutine of extract_normal.  */
 
 static CGEN_INLINE long
-extract_1 (cd, ex_info, start, length, word_length, bufp, pc)
+extract_1 (cd, start, length, word_length, bufp)
      CGEN_CPU_DESC cd;
-     CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED;
      int start,length,word_length;
      unsigned char *bufp;
-     bfd_vma pc ATTRIBUTE_UNUSED;
 {
   unsigned long x;
   int shift;
-#if 0
-  int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
-#endif
   x = cgen_get_insn_value (cd, bufp, word_length);
 
   if (CGEN_INSN_LSB0_P)
@@ -389,9 +336,7 @@ extract_1 (cd, ex_info, start, length, w
 
 /* Default extraction routine.
 
-   INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
-   or sometimes less for cases like the m32r where the base insn size is 32
-   but some insns are 16 bits.
+   INSN_VALUE is the first base_insn_bitsize bits of the insn in host order.
    ATTRS is a mask of the boolean attributes.  We only need `SIGNED',
    but for generality we take a bitmask of all of them.
    WORD_OFFSET is the offset in bits from the start of the insn of the value.
@@ -410,7 +355,7 @@ extract_1 (cd, ex_info, start, length, w
 static int
 extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
 		word_length, total_length, pc, valuep)
-     CGEN_CPU_DESC cd;
+     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
 #if ! CGEN_INT_INSN_P
      CGEN_EXTRACT_INFO *ex_info;
 #else
@@ -437,22 +382,12 @@ extract_normal (cd, ex_info, insn_value,
     }
 
 #if 0
-  if (CGEN_INT_INSN_P
-      && word_offset != 0)
-    abort ();
+  if (CGEN_INT_INSN_P)
+    assert (word_offset == 0);
 #endif
 
-  if (word_length > 32)
-    abort ();
-
-  /* For architectures with insns smaller than the insn-base-bitsize,
-     word_length may be too big.  */
-  if (cd->min_insn_bitsize < cd->base_insn_bitsize)
-    {
-      if (word_offset == 0
-	  && word_length > total_length)
-	word_length = total_length;
-    }
+  /* We currently don't handle word lengths > 32.  */
+  assert (word_length <= 32);
 
   /* Does the value reside in INSN_VALUE, and at the right alignment?  */
 
@@ -470,13 +405,12 @@ extract_normal (cd, ex_info, insn_value,
     {
       unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
 
-      if (word_length > 32)
-	abort ();
+      assert (word_length <= 32);
 
-      if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
+      if (cgen_fill_opcode_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
 	return 0;
 
-      value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
+      value = extract_1 (cd, start, length, word_length, bufp);
     }
 
 #endif /* ! CGEN_INT_INSN_P */
Index: opcodes/cgen-opc.c
===================================================================
RCS file: /cvs/src/src/opcodes/cgen-opc.c,v
retrieving revision 1.11
diff -u -p -r1.11 cgen-opc.c
--- opcodes/cgen-opc.c	19 Sep 2001 05:33:36 -0000	1.11
+++ opcodes/cgen-opc.c	6 Aug 2003 17:43:00 -0000
@@ -20,12 +20,14 @@
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "sysdep.h"
+#include <assert.h>
 #include <stdio.h>
 #include "ansidecl.h"
 #include "libiberty.h"
 #include "safe-ctype.h"
 #include "bfd.h"
 #include "symcat.h"
+#include "dis-asm.h"
 #include "opcode/cgen.h"
 
 #ifdef HAVE_ALLOCA_H
@@ -141,8 +143,7 @@ cgen_keyword_add (kt, ke)
 	/* 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 ();
+	assert (idx < sizeof (kt->nonalpha_chars) - 1);
 	kt->nonalpha_chars[idx] = ke->name[i];
 	kt->nonalpha_chars[idx+1] = 0;
       }
@@ -166,8 +167,7 @@ cgen_keyword_search_init (kt, spec)
   CGEN_KEYWORD_SEARCH search;
 
   /* FIXME: Need to specify format of PARAMS.  */
-  if (spec != NULL)
-    abort ();
+  assert (spec == NULL);
 
   if (kt->name_hash_table == NULL)
     build_keyword_hash_tables (kt);
@@ -400,8 +400,7 @@ cgen_get_insn_value (cd, buf, length)
       int i;
 
       /* Enforce divisibility. */ 
-      if ((length % insn_chunk_bitsize) != 0)
-	abort ();
+      assert ((length % insn_chunk_bitsize) == 0);
 
       for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
 	{
@@ -439,8 +438,7 @@ cgen_put_insn_value (cd, buf, length, va
       int i;
 
       /* Enforce divisibility. */ 
-      if ((length % insn_chunk_bitsize) != 0)
-	abort ();
+      assert ((length % insn_chunk_bitsize) == 0);
 
       for (i = 0; i < length; i += insn_chunk_bitsize) /* NB: i == bits */
 	{
@@ -533,8 +531,7 @@ cgen_lookup_insn (cd, insn, insn_int_val
 		  if (elength > 0)
 		    {
 		      /* sanity check */
-		      if (length != 0 && length != elength)
-			abort ();
+		      assert (length == 0 || length == elength);
 		      return insn;
 		    }
 		}
@@ -546,20 +543,16 @@ cgen_lookup_insn (cd, insn, insn_int_val
   else
     {
       /* Sanity check: can't pass an alias insn if ! alias_p.  */
-      if (! alias_p
-	  && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS))
-	abort ();
+      assert (! (! alias_p && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_ALIAS)));
       /* Sanity check: length must be correct.  */
-      if (length != CGEN_INSN_BITSIZE (insn))
-	abort ();
+      assert (length == CGEN_INSN_BITSIZE (insn));
 
       /* ??? 0 is passed for `pc' */
       length = CGEN_EXTRACT_FN (cd, insn)
 	(cd, insn, info, base_insn, fields, (bfd_vma) 0);
       /* Sanity check: must succeed.
 	 Could relax this later if it ever proves useful.  */
-      if (length == 0)
-	abort ();
+      assert (length != 0);
       return insn;
     }
 
@@ -580,8 +573,8 @@ cgen_get_insn_operands (cd, insn, fields
   const CGEN_OPINST *opinst;
   int i;
 
-  if (insn->opinst == NULL)
-    abort ();
+  assert (insn->opinst != NULL);
+
   for (i = 0, opinst = insn->opinst; opinst->type != CGEN_OPINST_END; ++i, ++opinst)
     {
       enum cgen_operand_type op_type = opinst->op_type;
@@ -647,4 +640,55 @@ cgen_signed_overflow_ok_p (cd)
      CGEN_CPU_DESC cd;
 {
   return cd->signed_overflow_ok_p;
+}
+
+/* Instruction building/unpacking support (insert/extract).
+   To be consistent this should live in cgen-ibld.c but there isn't enough
+   to go in there yet.  */
+
+/* Ensure sufficient bytes are cached in EX_INFO.
+   OFFSET is the offset in bytes from the start of the insn of the value.
+   BYTES is the length of the needed value.
+   Returns 1 for success, 0 for failure.  */
+
+int
+cgen_fill_opcode_cache (cd, ex_info, offset, bytes, pc)
+     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
+     CGEN_EXTRACT_INFO *ex_info;
+     int offset, bytes;
+     bfd_vma pc;
+{
+  /* It's doubtful that the middle part has already been fetched so
+     we don't optimize that case.  kiss.  */
+  unsigned int mask;
+  disassemble_info *info = (disassemble_info *) ex_info->dis_info;
+
+  /* First do a quick check.  */
+  mask = (1 << bytes) - 1;
+  if (((ex_info->valid >> offset) & mask) == mask)
+    return 1;
+
+  /* Search for the first byte we need to read.  */
+  for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
+    if (! (mask & ex_info->valid))
+      break;
+
+  if (bytes)
+    {
+      int status;
+
+      pc += offset;
+      status = (*info->read_memory_func)
+	(pc, ex_info->insn_bytes + offset, bytes, info);
+
+      if (status != 0)
+	{
+	  (*info->memory_error_func) (status, pc, info);
+	  return 0;
+	}
+
+      ex_info->valid |= ((1 << bytes) - 1) << offset;
+    }
+
+  return 1;
 }
Index: cgen/decode.scm
===================================================================
RCS file: /cvs/src/src/cgen/decode.scm,v
retrieving revision 1.8
diff -u -p -r1.8 decode.scm
--- cgen/decode.scm	17 Jul 2003 06:19:35 -0000	1.8
+++ cgen/decode.scm	6 Aug 2003 17:43:12 -0000
@@ -182,6 +182,8 @@
 (define (dtable-entry-type te) (vector-ref te 1))
 (define (dtable-entry-value te) (vector-ref te 2))
 
+; decode-get-best bits
+
 ; Return #t if BITNUM is a good bit to use for decoding.
 ; MASKS is a list of opcode masks.
 ; MASK-LENS is a list of lengths of each value in MASKS.
@@ -200,6 +202,9 @@
 ; FIXME: Bit numbers shouldn't be considered in isolation.
 ; It would be better to compute use counts of all of them and then see
 ; if there's a cluster of high use counts.
+;
+; NOTE: Subroutine of OLDdecode-get-best-bits which is no longer used.
+; Kept for reference.
 
 (define (-usable-decode-bit? masks mask-lens bitnum lsb0?)
   (let* ((has-bit (map (lambda (msk len)
@@ -227,15 +232,17 @@
 	 (num-insns (length masks)))
     ; Compute the 1- and 0-population vectors
     (for-each (lambda (mask len value)
-		(logit 5 " population count mask=" (number->hex mask) " len=" len "\n")
+		(logit 5 " population count mask=0x" (number->hex mask)
+		       " len=" len "\n")
 		(for-each (lambda (bitno)
 			    (let ((lsb-bitno (if lsb0? bitno (- len bitno 1))))
 			      ; ignore this bit if it's not set in the mask
 			      (if (bit-set? mask lsb-bitno)
 				(let ((chosen-pop-vector (if (bit-set? value lsb-bitno)
-							     1-population 0-population)))
+							     1-population
+							     0-population)))
 				  (vector-set! chosen-pop-vector bitno 
-					     (+ 1 (vector-ref chosen-pop-vector bitno)))))))
+					       (+ 1 (vector-ref chosen-pop-vector bitno)))))))
 			  (-range len)))
 	      masks mask-lens values)
     ; Compute an aggregate "distinguishing value" for each bit.
@@ -350,56 +357,59 @@
 		(* 0.75 count-threshold))))))
 )
 
-; Given list of insns, return list of bit numbers of constant bits in opcode
-; that they all share (or mostly share), up to MAX elements.
-; ALREADY-USED is a list of bitnums we can't use.
-; STARTBIT is the bit offset of the instruction value that C variable `insn'
-; holds (note that this is independent of LSB0?).
-; DECODE-BITSIZE is the number of bits of the insn that `insn' holds.
+; Given a list of insns, return list of bit numbers of constant bits in opcode
+; that they all share (or mostly share), up to MAX elements, in the word
+; specified by STARTBIT,DECODE-BITSIZE.
+; ALREADY-USED is a list of bitnums we can't use, relative to the word
+; under consideration.
+; STARTBIT,DECODE-BITSIZE specify the insn word under consideration.
 ; LSB0? is non-#f if bit number 0 is the least significant bit.
 ;
+; The result is for the word under consideration.  E.g. If an insn has
+; two 16 bit words, when processing the second word BITNUMS has values 0-15.
 ; Nil is returned if there are none, meaning that there is an ambiguity in
 ; the specification up to the current word.
 ;
-; We assume INSN-LIST matches all opcode bits before STARTBIT.
-; FIXME: Revisit, as a more optimal decoder is sometimes achieved by doing
-; a cluster of opcode bits that appear later in the insn, and then coming
-; back to earlier ones.
-;
-; All insns are assumed to start at the same address so we handle insns of
-; varying lengths - we only analyze the common bits in all of them.
+; NOTE: This function only operates on one insn word.  Whether opcode bits in
+; previous or later words match is the caller's business.
 ;
-; Note that if we get called again to compute further opcode bits, we
-; start looking at STARTBIT again (rather than keeping track of how far in
-; the insn word we've progressed).  We could do this as an optimization, but
-; we also have to handle the case where the initial set of decode bits misses
-; some and thus we have to go back and look at them.  It may also turn out
-; that an opcode bit is skipped over because it doesn't contribute much
-; information to the decoding process (see -usable-decode-bit?).  As the
-; possible insn list gets wittled down, the bit will become significant.  Thus
-; the optimization is left for later.  Also, see preceding FIXME.
-
-(define (decode-get-best-bits insn-list already-used startbit max decode-bitsize lsb0?)
-  (let* ((raw-population (-distinguishing-bit-population (map insn-base-mask insn-list)
-							 (map insn-base-mask-length insn-list)
-							 (map insn-value insn-list)
-							 lsb0?))
-	 ; (undecoded (if lsb0?
-	; 		(-range2 startbit (+ startbit decode-bitsize))
-		;	(-range2 (- startbit decode-bitsize) startbit)))
+; NOTE: All insns are assumed to share the insn word specified by STARTBIT,
+; DECODE-BITSIZE.
+
+(define (decode-get-best-bits insn-list already-used max
+			      startbit decode-bitsize lsb0?)
+  (let* ((raw-population
+	  (-distinguishing-bit-population (map (lambda (insn)
+						 (insn-mask-at-offset insn startbit))
+					       insn-list)
+					  (map (lambda (insn)
+						 (insn-mask-length-at-offset insn startbit))
+					       insn-list)
+					  (map (lambda (insn)
+						 (insn-value-at-offset insn startbit))
+					       insn-list)
+					  lsb0?))
+	 ;(undecoded (if lsb0?
+	 ;		(-range2 startbit (+ startbit decode-bitsize))
+	 ;		(-range2 (- startbit decode-bitsize) startbit)))
 	 (used+undecoded already-used) ; (append already-used undecoded))
 	 (filtered-population (-vector-copy-set-all raw-population used+undecoded #f))
 	 (favorite-indices (-population-top-few filtered-population max))
-	 (sorted-indices (sort favorite-indices (lambda (a b) 
-						  (if lsb0? (> a b) (< a b))))))
+	 (sorted-indices (sort favorite-indices
+			       (lambda (a b) 
+				 (if lsb0? (> a b) (< a b))))))
     (logit 3 
-	   "Best decode bits (prev=" already-used " start=" startbit " decode=" decode-bitsize ")"
+	   "Best decode bits (prev=" already-used " word-offset=" startbit " word-bitsize=" decode-bitsize ")"
 	   "=>"
 	   "(" sorted-indices ")\n")
     sorted-indices)
 )
 
-(define (OLDdecode-get-best-bits insn-list already-used startbit max decode-bitsize lsb0?)
+; NOTE: No longer used.  Kept for reference.
+
+(define (OLDdecode-get-best-bits insn-list already-used max
+				 startbit decode-bitsize lsb0?)
+  ; NOTE: bitrotted, needs to use insn-mask-at-offset, etc.
   (let ((masks (map insn-base-mask insn-list))
 	; ??? We assume mask lengths are repeatedly used for insns longer
 	; than the base insn size.
@@ -420,50 +430,62 @@
 	      (loop result (+ bitnum incr))))
       ))
 )
+
+; -build-slots
+
+; ???
+
+(define (-opcode-compute val insn-len decode-len bl lsb0?)
+  ;(display (list val insn-len decode-len bl)) (newline)
+  ; Oh My God.  This isn't tail recursive.
+  (if (null? bl)
+      0
+      (+ (if (> (car bl) insn-len)
+	     0
+	     (if (bit-set? val
+			   (if lsb0?
+			       (car bl)
+			       (- insn-len (car bl) 1)))
+		 (integer-expt 2 (- (length bl) 1))
+		 0))
+	 (-opcode-compute val insn-len decode-len (cdr bl) lsb0?)))
+)
 
 ; Return list of decode table entry numbers for INSN's opcode bits BITNUMS.
-; This is the indices into the decode table that match the instruction.
+; The result is the indices into the decode table that match the instruction.
+; BITNUMS is relative to the word under consideration.  E.g. If an insn has
+; two 16 bit words, when processing the second word BITNUMS has values 0-15.
+; WORD-OFFSET,WORD-BITSIZE specify the word under consideration.
 ; LSB0? is non-#f if bit number 0 is the least significant bit.
 ;
 ; Example: If BITNUMS is (0 1 2 3 4 5), and the constant (i.e. opcode) part of
-; the those bits of INSN is #b1100xx (where 'x' indicates a non-constant
+; those bits of INSN is #b1100xx (where 'x' indicates a non-constant
 ; part), then the result is (#b110000 #b110001 #b110010 #b110011).
 
-(define (-opcode-slots insn bitnums lsb0?)
-  (letrec ((opcode (insn-value insn))
-	   (insn-len (insn-base-mask-length insn))
-	   (decode-len (length bitnums))
-	   (compute (lambda (val insn-len decode-len bl)
-		      ;(display (list val insn-len decode-len bl)) (newline)
-		      ; Oh My God.  This isn't tail recursive.
-		      (if (null? bl)
-			  0
-			  (+ (if (> (car bl) insn-len)
-				 0
-				 (if (bit-set? val
-					       (if lsb0?
-						   (car bl)
-						   (- insn-len (car bl) 1)))
-				     (integer-expt 2 (- (length bl) 1))
-				     0))
-			     (compute val insn-len decode-len (cdr bl)))))))
-    (let* ((opcode (compute (insn-value insn) insn-len decode-len bitnums))
-	   (opcode-mask (compute (insn-base-mask insn) insn-len decode-len bitnums))
+(define (-opcode-slots insn bitnums word-offset word-bitsize lsb0?)
+  (let ((mask (insn-mask-at-offset insn word-offset))
+	(value (insn-value-at-offset insn word-offset))
+	(decode-len (length bitnums)))
+    (let* ((opcode (-opcode-compute value word-bitsize decode-len bitnums lsb0?))
+	   (opcode-mask (-opcode-compute mask word-bitsize decode-len bitnums lsb0?))
 	   (indices (missing-bit-indices opcode-mask (- (integer-expt 2 decode-len) 1))))
       (logit 3 "insn =" (obj:name insn)
-	     " insn-base-value=" (insn-base-value insn)
-	     " insn-base-mask=" (insn-base-mask insn)
-	     " insn-len=" insn-len
+	     " word-offset=" word-offset
+	     " word-bitsize=" word-bitsize
+	     " insn-value=" value
+	     " insn-mask=" mask
 	     " decode-len=" decode-len
 	     " opcode=" opcode
 	     " opcode-mask=" opcode-mask
 	     " indices=" indices "\n")
-      (map (lambda (index) (+ opcode index)) indices)))
+      (map (lambda (index) (+ opcode index))
+	   indices)))
 )
 
 ; Subroutine of -build-slots.
 ; Fill slot in INSN-VEC that INSN goes into.
-; BITNUMS is the list of opcode bits.
+; BITNUMS is the list of opcode bits, relative to the word under consideration.
+; WORD-OFFSET,WORD-BITSIZE specify the word under consideration.
 ; LSB0? is non-#f if bit number 0 is the least significant bit.
 ;
 ; Example: If BITNUMS is (0 1 2 3 4 5) and the constant (i.e. opcode) part of
@@ -471,9 +493,9 @@
 ; part), then elements 48 49 50 51 of INSN-VEC are cons'd with INSN.
 ; Each "slot" is a list of matching instructions.
 
-(define (-fill-slot! insn-vec insn bitnums lsb0?)
+(define (-fill-slot! insn-vec insn bitnums word-offset word-bitsize lsb0?)
   ;(display (string-append "fill-slot!: " (obj:str-name insn) " ")) (display bitnums) (newline)
-  (let ((slot-nums (-opcode-slots insn bitnums lsb0?)))
+  (let ((slot-nums (-opcode-slots insn bitnums word-offset word-bitsize lsb0?)))
     ;(display (list "Filling slot(s)" slot-nums "...")) (newline)
     (for-each (lambda (slot-num)
 		(vector-set! insn-vec slot-num
@@ -484,16 +506,20 @@
 )
 
 ; Given a list of constant bitnums (ones that are predominantly, though perhaps
-; not always, in the opcode), record each insn in INSN-LIST in the proper slot.
+; not always, in the opcode) in the word specified by WORD-OFFSET,WORD-BITSIZE,
+; return a vector with each insn in INSN-LIST recorded in the proper slot.
 ; LSB0? is non-#f if bit number 0 is the least significant bit.
 ; The result is a vector of insn lists.  Each slot is a list of insns
 ; that go in that slot.
+;
+; NOTE: BITNUMS is for the word under consideration.  E.g. If an insn has
+; two 16 bit words, when processing the second word BITNUMS has values 0-15.
 
-(define (-build-slots insn-list bitnums lsb0?)
+(define (-build-slots insn-list bitnums word-offset word-bitsize lsb0?)
   (let ((result (make-vector (integer-expt 2 (length bitnums)) nil)))
     ; Loop over each element, filling RESULT.
     (for-each (lambda (insn)
-		(-fill-slot! result insn bitnums lsb0?))
+		(-fill-slot! result insn bitnums word-offset word-bitsize lsb0?))
 	      insn-list)
     result)
 )
@@ -517,9 +543,12 @@
 ; INSN-VEC is a vector of slots where each slot is a list of instructions that
 ; map to that slot (opcode value).  If a slot is nil, no insn has that opcode
 ; value so the decoder marks it as being invalid.
-; STARTBIT is the bit offset of the instruction value that C variable `insn'
-; holds (note that this is independent of LSB0?).
-; DECODE-BITSIZE is the number of bits of the insn that `insn' holds.
+; STARTBIT,DECODE-BITSIZE specify the current word being used to decode insns.
+; We assume all bits of all previous words have been completely used.
+; If there are ambiguities after fully using the current word, we move to the
+; next word.
+; NOTE: We (currently) assume all insns in any one slot have the same word
+; sizes up to the point where they're fully distinguished.
 ; INDEX-LIST is a list of pairs: list of bitnums, table entry number.
 ; LSB0? is non-#f if bit number 0 is the least significant bit.
 ; INVALID-INSN is an <insn> object to use for invalid insns.
@@ -528,7 +557,8 @@
 ; ??? For debugging.
 (define -build-decode-table-entry-args #f)
 
-(define (-build-decode-table-entry insn-vec startbit decode-bitsize index index-list lsb0? invalid-insn)
+(define (-build-decode-table-entry insn-vec startbit decode-bitsize
+				   index index-list lsb0? invalid-insn)
   (let ((slot (vector-ref insn-vec index)))
     (logit 2 "Processing decode entry "
 	   (number->string index)
@@ -553,7 +583,8 @@
      ; further opcode bits.
      (else
       (logit 3 "Building subtable at index " (number->string index)
-	     ", decode-bitsize = " (number->string decode-bitsize)
+	     ", word-offset = " (number->string startbit)
+	     ", word-bitsize = " (number->string decode-bitsize)
 	     ", indices used thus far:"
 	     (string-map (lambda (i) (string-append " " (number->string i)))
 			 (apply append (map car index-list)))
@@ -561,8 +592,7 @@
 
       (let ((bitnums (decode-get-best-bits slot
 					   (apply append (map car index-list))
-					   startbit 4
-					   decode-bitsize lsb0?)))
+					   4 startbit decode-bitsize lsb0?)))
 
 	; If bitnums is nil, either there is an ambiguity or we need to read
 	; more of the instruction in order to distinguish insns in SLOT.
@@ -573,17 +603,27 @@
 	      ; We know from the < test that there are, indeed, more bits to
 	      ; be read.
 	      (set! startbit (+ startbit decode-bitsize))
-	      ; FIXME: The calculation of the new decode-bitsize will
-	      ; undoubtedly need refinement.
-	      (set! decode-bitsize
-		    (min decode-bitsize
-			 (- (apply min (map insn-length slot))
-			    startbit)))
-	      (set! bitnums (decode-get-best-bits slot
-						  ;nil ; FIXME: what to put here?
-						  (apply append (map car index-list))
-						  startbit 4
-						  decode-bitsize lsb0?))))
+	      ; If we've used up all of one insn, there's a definite ambiguity.
+	      (if (any-true? (map (lambda (insn)
+				    (= startbit (insn-length insn)))
+				  slot))
+		  #t ; leave bitnums = nil.
+		  (begin
+		    (set! decode-bitsize (insn-mask-length-at-offset (car slot) startbit))
+		    ; We (currently) require all insns have the same word sizes up to
+		    ; the point where they're distinguished.
+		    (if (not (all-true? (map (lambda (insn)
+					       (= decode-bitsize (insn-mask-length-at-offset insn startbit)))
+					     slot)))
+			(message "WARNING: Decoder detected word mismatch.\n"
+				 "All words up to and including point where insns are distinguished\n"
+				 "must have same sizes.\n"
+				 "Insns:" (map (lambda (insn)
+						 (string-append " " (obj:str-name insn)))
+					       slot)
+				 "\n"))
+		    (set! bitnums (decode-get-best-bits slot nil
+							4 startbit decode-bitsize lsb0?))))))
 
 	; If bitnums is still nil there is an ambiguity.
 	(if (null? bitnums)
@@ -619,11 +659,11 @@
 		        ; Otherwise, see if any ifield-assertion
 			; specs are present.
 			; FIXME: For now we assume that if they all have an
-			; ifield-assertion spec, then there is no ambiguity (it's left
-			; to the programmer to get it right).  This can be made more
-			; clever later.
-			; FIXME: May need to back up startbit if we've tried to read
-			; more of the instruction.
+			; ifield-assertion spec, then there is no ambiguity
+			; (it's left to the programmer to get it right).
+			; This can be made more clever later.
+			; FIXME: May need to back up startbit if we've tried
+			; to read more of the instruction.
 			(let ((assertions (map insn-ifield-assertion slot)))
 			  (if (not (all-true? assertions))
 			      (begin
@@ -644,7 +684,7 @@
 	    ; There is no ambiguity so generate the subtable.
 	    ; Need to build `subtable' separately because we
 	    ; may be appending to -decode-subtables recursively.
-	    (let* ((insn-vec (-build-slots slot bitnums lsb0?))
+	    (let* ((insn-vec (-build-slots slot bitnums startbit decode-bitsize lsb0?))
 		   (subtable
 		    (-build-decode-table-guts insn-vec bitnums startbit
 					      decode-bitsize index-list lsb0?
@@ -663,19 +703,18 @@
 ; -decode-subtables.  Not sure this will ever happen, but play it safe.
 ;
 ; BITNUMS is the list of bit numbers used to build the slot table.
-; STARTBIT is the bit offset of the instruction value that C variable `insn'
-; holds (note that this is independent of LSB0?).
-; For example, it is initially zero.  If DECODE-BITSIZE is 16 and after
-; scanning the first fetched piece of the instruction, more decoding is
-; needed, another piece will be fetched and STARTBIT will then be 16.
-; DECODE-BITSIZE is the number of bits of the insn that `insn' holds.
+; It is relative to the word under consideration.  E.g. If an insn has
+; two 16 bit words, when processing the second word BITNUMS has values 0-15.
+; STARTBIT,DECODE-BITSIZE specify the current word being used to decode insns.
+; We assume all bits of all previous words have been completely used.
 ; INDEX-LIST is a list of pairs: list of bitnums, table entry number.
 ; Decode tables consist of entries of two types: actual insns and
 ; pointers to other tables.
 ; LSB0? is non-#f if bit number 0 is the least significant bit.
 ; INVALID-INSN is an <insn> object representing invalid insns.
 
-(define (-build-decode-table-guts insn-vec bitnums startbit decode-bitsize index-list lsb0? invalid-insn)
+(define (-build-decode-table-guts insn-vec bitnums startbit decode-bitsize
+				  index-list lsb0? invalid-insn)
   (logit 2 "Processing decoder for bits"
 	 (numbers->string bitnums " ")
 	 " ...\n")
@@ -689,11 +728,13 @@
 				     lsb0? invalid-insn))
 	(iota (vector-length insn-vec))))
 )
-
+
 ; Entry point.
+
 ; Return a table that efficiently decodes INSN-LIST.
-; BITNUMS is the set of bits to initially key off of.
-; DECODE-BITSIZE is the number of bits of the instruction that `insn' holds.
+; BITNUMS is the set of bits in the base insn word to initially key off of.
+; DECODE-BITSIZE is the number of bits of the base insn word.
+; Basically it's base-insn-size.
 ; LSB0? is non-#f if bit number 0 is the least significant bit.
 ; INVALID-INSN is an <insn> object representing the `invalid' insn (for
 ; instructions values that don't decode to any entry in INSN-LIST).
@@ -710,7 +751,7 @@
   ; that recorded the necessary bits (insn, ifield-list, remaining
   ; ifield-assertions).
 
-  (let ((insn-vec (-build-slots insn-list bitnums lsb0?)))
+  (let ((insn-vec (-build-slots insn-list bitnums 0 decode-bitsize lsb0?)))
     (let ((table-guts (-build-decode-table-guts insn-vec bitnums
 						0 decode-bitsize
 						nil lsb0?
Index: cgen/html.scm
===================================================================
RCS file: /cvs/src/src/cgen/html.scm,v
retrieving revision 1.6
diff -u -p -r1.6 html.scm
--- cgen/html.scm	16 Jul 2003 05:35:47 -0000	1.6
+++ cgen/html.scm	6 Aug 2003 17:43:12 -0000
@@ -555,8 +555,8 @@ See the input .cpu file(s) for copyright
 ; Generate a diagram typically used to display instruction fields.
 
 (define (gen-iformat-table insn)
-  (let* ((lsb0? (current-arch-insn-lsb0?))
-	 (sorted-iflds (sort-ifield-list (insn-iflds insn) (not lsb0?))))
+  (let ((lsb0? (current-arch-insn-lsb0?))
+	(sorted-iflds (insn-sorted-iflds insn)))
     (let ((widths (map ifld-length sorted-iflds))
 	  (names (map obj:name sorted-iflds))
 	  (operands (map (lambda (f)
Index: cgen/ifield.scm
===================================================================
RCS file: /cvs/src/src/cgen/ifield.scm,v
retrieving revision 1.7
diff -u -p -r1.7 ifield.scm
--- cgen/ifield.scm	16 Jul 2003 05:35:47 -0000	1.7
+++ cgen/ifield.scm	6 Aug 2003 17:43:13 -0000
@@ -57,9 +57,9 @@
 	      nil)
 )
 
-; {value},{follows} are missing on purpose
+; {value},{follows} are missing on purpose.
 ; {value} is handled specially.
-; {follows} is rarely used
+; {follows} is rarely used.
 (method-make-make! <ifield> '(name comment attrs mode bitrange encode decode))
 
 ; Accessor fns
@@ -158,7 +158,7 @@
 				(gen-sym ifld)))
 )
 
-; Return a boolean indicating if ifield F is an opcode field
+; Return a boolean indicating if <ifield> F is an opcode field
 ; (has a constant value).
 
 (define (ifld-constant? f)
@@ -169,6 +169,15 @@
 ;	   (not (has-attr? f 'RESERVED))))
 )
 
+; Return an <ifield> F's constant value or #f if not constant.
+
+(define (ifld-constant-value f)
+  (let ((v (ifld-get-value f)))
+    (if (number? v)
+	v
+	#f))
+)
+
 ; Return a boolean indicating if ifield F is an operand.
 ; FIXME: Should check for operand? or some such.
 
@@ -237,6 +246,7 @@
 ; BASE-LEN, if non-#f, overrides the base insn length of the insn.
 ; BASE-LEN is present for architectures like the m32r where there are insns
 ; smaller than the base insn size (LIW).
+; If VALUE is #f, use the ifield's value (must be a constant).
 
 (method-make!
  <ifield> 'field-value
@@ -246,6 +256,8 @@
 	  (word-offset (bitrange-word-offset bitrange))
 	  (word-length (or (and (= word-offset 0) base-len)
 			   recorded-word-length)))
+     (if (not value)
+	 (set! value (ifld-get-value self)))
      (word-value (ifld-start self base-len)
 		 (bitrange-length bitrange)
 		 word-length
@@ -687,7 +699,7 @@ Define an instruction multi-field, name/
 		       "\
 Define an instruction multi-field, all arguments specified.
 "
-		       nil '(name comment attrs mode subflds insert extract)
+		       nil '(name comment attrs mode subflds insert extract encode decode)
 		       define-full-multi-ifield)
 
   *UNSPECIFIED*
@@ -705,10 +717,15 @@ Define an instruction multi-field, all a
 		insert
 		; rtl to set self from SUBFIELDS
 		extract
+
+		; sorted version of subfields, lazily cached
+		(sorted-subfields . #f)
 		)
 	      nil)
 )
 
+(method-make-make! <multi-ifield> '(name comment attrs subfields insert extract))
+
 ; Accessors
 
 (define-getters <multi-ifield> multi-ifld
@@ -727,7 +744,6 @@ Define an instruction multi-field, all a
   (find (lambda (ifld) (not (derived-ifield? ifld))) ifld-list)
 )
 
-
 ; Return the starting bit number of the first field.
 
 (method-make-virtual!
@@ -789,8 +805,7 @@ Define an instruction multi-field, all a
 (method-make!
  <multi-ifield> 'field-extract
  (lambda (self insn value)
-   (let* ((subflds (sort-ifield-list (elm-get self 'subfields)
-				     (not (ifld-lsb0? self))))
+   (let* ((subflds (multi-ifld-sorted-subfields self))
 	  (subvals (map (lambda (subfld)
 			  (ifld-extract subfld insn value))
 			subflds))
@@ -815,6 +830,17 @@ Define an instruction multi-field, all a
  (lambda (self)
    (ifld-lsb0? (car (elm-get self 'subfields))))
 )
+
+; Return list of sorted subfields.
+; The result is cached to speed up the next call.
+
+(define (multi-ifld-sorted-subfields mf)
+  (if (elm-get mf 'sorted-subfields)
+      (elm-get mf 'sorted-subfields)
+      (let ((ssf (sort-ifield-list (elm-get mf 'subfields))))
+	(elm-set! mf 'sorted-subfields ssf)
+	ssf))
+)
 
 ; Multi-ifield parsing.
 
@@ -949,9 +975,10 @@ Define an instruction multi-field, all a
 
 ; Define an instruction multi-field object, all arguments specified.
 
-(define (define-full-multi-ifield name comment attrs mode subflds insert extract)
+(define (define-full-multi-ifield name comment attrs mode subflds
+	  insert extract encode decode)
   (let ((f (-multi-ifield-parse "define-full-multi-ifield" name comment attrs
-				mode subflds insert extract #f #f)))
+				mode subflds insert extract encode decode)))
     (current-ifld-add! f)
     f)
 )
@@ -985,7 +1012,6 @@ Define an instruction multi-field, all a
 	      nil)
 )
 
-
 (method-make!
  <derived-ifield> 'needed-iflds
  (lambda (self)
@@ -993,7 +1019,6 @@ Define an instruction multi-field, all a
 	 (elm-get self 'subfields)))
 )
 
-
 (method-make!
  <derived-ifield> 'make!
  (lambda (self name comment attrs owner subfields)
@@ -1035,8 +1060,8 @@ Define an instruction multi-field, all a
 		   (derived-ifield-subfields self))))
 )
 
-
 ; Traverse the ifield to collect all base (non-derived) ifields used in it.
+
 (define (ifld-base-ifields ifld)
   (cond ((derived-ifield? ifld) (collect (lambda (subfield) (ifld-base-ifields subfield))
 					 (derived-ifield-subfields ifld)))
@@ -1046,9 +1071,35 @@ Define an instruction multi-field, all a
 )
 
 
+; Traverse the ifield to collect all real (non-derived and non-multi) ifields
+; used in it.
+
+(define (ifld-real-ifields ifld)
+  (cond ((derived-ifield? ifld) (collect (lambda (subfield)
+					   (ifld-base-ifields subfield))
+					 (derived-ifield-subfields ifld)))
+	((multi-ifield? ifld) (collect (lambda (subfield)
+					 (ifld-base-ifields subfield))
+				       (multi-ifld-subfields ifld)))
+	(else (list ifld)))
+)
 
 ; Misc. utilities.
 
+; Subroutine of sort-ifield-list.
+; Return the starting bit number to use to sort F.
+; Fields are always sorted so that the field with the MSB of the first word
+; of the insn comes first.
+
+(define (-ifld-start-bit-for-sort f)
+  (if (multi-ifield? f)
+      (-ifld-start-bit-for-sort (car (multi-ifld-sorted-subfields f)))
+      (+ (ifld-word-offset f)
+	 (if (ifld-lsb0? f)
+	     (- (ifld-word-length f) 1 (ifld-start f #f))
+	     (ifld-start f #f))))
+)
+
 ; Sort a list of fields (sorted by the starting bit number).
 ; This must be carefully defined to pass through Hobbit.
 ; (define foo (if x bar baz)) is ok.
@@ -1057,25 +1108,22 @@ Define an instruction multi-field, all a
 ; ??? Usually there aren't that many fields and the range of values is fixed,
 ; so I think this needn't use a general purpose sort routine (should it become
 ; an issue).
+;
+; The sort is done first on the containing word and then on the position
+; within that word.
 
 (define sort-ifield-list
   (if (and (defined? 'cgh-qsort) (defined? 'cgh-qsort-int-cmp))
-      (lambda (fld-list up?)
+      (lambda (fld-list)
 	(cgh-qsort fld-list
-		   (if up?
-		       (lambda (a b)
-			 (cgh-qsort-int-cmp (ifld-start a #f)
-					    (ifld-start b #f)))
-		       (lambda (a b)
-			 (- (cgh-qsort-int-cmp (ifld-start a #f)
-					       (ifld-start b #f)))))))
-      (lambda (fld-list up?)
+		   (lambda (a b)
+		     (cgh-qsort-int-cmp (-ifld-start-bit-for-sort a)
+					(-ifld-start-bit-for-sort b)))))
+      (lambda (fld-list)
 	(sort fld-list
-	      (if up?
-		  (lambda (a b) (< (ifld-start a #f)
-				   (ifld-start b #f)))
-		  (lambda (a b) (> (ifld-start a #f)
-				   (ifld-start b #f)))))))
+	      (lambda (a b)
+		(< (-ifld-start-bit-for-sort a)
+		   (-ifld-start-bit-for-sort b))))))
 )
 
 ; Return a boolean indicating if field F extends beyond the base insn.
Index: cgen/iformat.scm
===================================================================
RCS file: /cvs/src/src/cgen/iformat.scm,v
retrieving revision 1.4
diff -u -p -r1.4 iformat.scm
--- cgen/iformat.scm	16 Jul 2003 05:35:47 -0000	1.4
+++ cgen/iformat.scm	6 Aug 2003 17:43:13 -0000
@@ -23,7 +23,7 @@
 ; in the modeling code.
 ;
 ; The "base length" is the length of the insn that is initially fetched for
-; decoding purposes.
+; decoding purposes (base-insn-size).
 ; Formats are fixed in length.  For variable instruction length architectures
 ; there are separate formats for each insn's possible length.
 
@@ -46,14 +46,16 @@
 		; List of <ifield> objects.
 		ifields
 
-		; min (insn-length, base-insn-size)
-		mask-length
-
 		; total length of insns with this format
 		length
 
+		; list of lengths of each element of the instruction
+		; Example: In an insn with a 16 bit opcode followed by a
+		; 32 bit immediate value this would be (16 32).
+		mask-lengths
+
 		; mask of base part
-		mask
+		masks
 
 		; An example insn that uses the format.
 		eg-insn
@@ -64,7 +66,7 @@
 ; Accessor fns.
 
 (define-getters <iformat> ifmt
-  (number key ifields mask-length length mask eg-insn)
+  (number key ifields length mask-lengths masks eg-insn)
 )
 
 ; Traverse the ifield list to collect all base (non-derived) ifields used in it.
@@ -89,20 +91,79 @@
   (apply + (map ifld-length (collect ifld-base-ifields fld-list)))
 )
 
+; Utility to return (word-start . word-length) for <ifield> f.
+
+(define (-ifmt-ifield-word f)
+  (cons (ifld-word-offset f) (ifld-word-length f))
+)
+
+; Given sorted FLD-LIST, compute the list of words.
+; The result is a sorted list of (word-start . word-length) pairs.
+
+(define (compute-insn-words fld-list)
+  ; Collect the list of "words" the ifields are in, and the remove duplicates.
+  ; NOTE: "word" here is a misnomer but I can't think of a better name.
+  (remove-duplicates (map (lambda (f)
+			    (-ifmt-ifield-word f))
+			  ; Have to resort the list in case of multi-ifields.
+			  (sort-ifield-list
+			   (collect ifld-real-ifields fld-list))))
+)
+
+; Given sorted FLD-LIST, compute the opcode mask lengths.
+; If the instruction is base-insn-bitsize in length, there is just one mask.
+; Otherwise there are several.
+; Masks can be of different sizes.
+; Example: an insn with a 16 bit opcode and a 32 bit immediate value has
+; masks (16 32).
+
+(define (compute-insn-mask-lengths fld-list)
+  (let ((words (compute-insn-words fld-list)))
+    ; We now have a sorted list of (word-start . word-length) pairs.
+    ; We just want the word lengths.
+    (map cdr words))
+)
+
+; Given sorted FLD-LIST, compute the opcode masks.
+; There is one element for each element of
+; (compute-insn-mask-lengths fld-list).
+
+(define (compute-insn-masks fld-list)
+  ; Break out multi-ifields.
+  (set! fld-list (sort-ifield-list (collect ifld-real-ifields fld-list)))
+  ; First sort the fields into bins of each "word".
+  (let* ((words (compute-insn-words fld-list))
+	 (bins (map (lambda (word) (cons word '())) words)))
+    (for-each (lambda (f)
+		; ??? Arguably not very efficient.  Optimize later.
+		(let ((fword (-ifmt-ifield-word f)))
+		  (assoc-set! bins fword (cons f (assoc-ref bins fword)))))
+	      fld-list)
+
+    ; Now compute the masks for each word.
+    (map (lambda (bin)
+	   (apply + (map (lambda (f)
+			   (ifld-mask f #f #f))
+			 ; Find the fields that have constant values.
+			 (find ifld-constant?
+			       (cdr bin)))))
+	 bins))
+)
+
 ; Given FLD-LIST, compute the base length in bits.
 ;
 ; For variable length instruction sets, or with cpus with multiple
 ; instruction sets, compute the base appropriate for this set of
 ; ifields.  Check that ifields are not shared among isas with
 ; inconsistent base insn lengths.
+; FIXME: no longer used, delete in time
 
 (define (compute-insn-base-mask-length fld-list)
   (let* ((isa-base-bitsizes
 	  (remove-duplicates
 	   (map isa-base-insn-bitsize
 		(map current-isa-lookup
-		     (collect (lambda (ifld) 
-				(bitset-attr->list (atlist-attr-value (obj-atlist ifld) 'ISA #f)))
+		     (collect (lambda (ifld) (obj-isa-list ifld))
 			      fld-list))))))
     (if (= 1 (length isa-base-bitsizes))
 	(min (car isa-base-bitsizes) (compute-insn-length fld-list))
@@ -111,14 +172,8 @@
 
 ; Given FLD-LIST, compute the bitmask of constant values in the base part
 ; of the insn (i.e. the opcode field).
-;
-; FIXME: Need to add support for constant fields appearing outside the base
-; insn.  One way would be to record with each insn the value for each constant
-; field.  That would allow code to straightforwardly fetch it.  Another would
-; be to only record constant values appearing outside the base insn.
-;
-; See also (insn-value).
-;
+; FIXME: no longer used, delete in time
+
 (define (compute-insn-base-mask fld-list)
   (let* ((mask-len (compute-insn-base-mask-length fld-list))
 	 (lsb0? (ifld-lsb0? (car fld-list)))
@@ -156,23 +211,41 @@
 	      sorted-ifld-list)
 )
 
+; Validate an <ifmt-desc> object.
+; Check for
+; - missing/overlapping bits (TODO)
+; - insn smaller than base-insn-size
+
+(define (-ifmt-desc-validate desc)
+  *UNSPECIFIED*
+)
+
 ; Create an <iformat> object for INSN.
 ; INDEX is the ordinal to assign to the result or -1 if unknown.
 ; SEARCH-KEY is the search key used to determine the iformat's uniqueness.
 ; IFLDS is a sorted list of INSN's ifields.
 
 (define (ifmt-build insn index search-key iflds)
-  (make <iformat>
-    (symbol-append 'ifmt- (obj:name insn))
-    (string-append "e.g. " (insn-syntax insn))
-    atlist-empty
-    index
-    search-key
-    iflds
-    (compute-insn-base-mask-length iflds)
-    (compute-insn-length iflds)
-    (compute-insn-base-mask iflds)
-    insn)
+  (let ((length (compute-insn-length iflds)))
+
+    ; Do various checks
+    ; TODO: check for missing/overlapping bits
+    (if (< length (state-base-insn-bitsize))
+	(message "WARNING: insn smaller than base-insn-bitsize: "
+		 (obj:name insn)
+		 "\n"))
+
+    (make <iformat>
+      (symbol-append 'ifmt- (obj:name insn))
+      (string-append "e.g. " (insn-syntax insn))
+      atlist-empty
+      index
+      search-key
+      iflds
+      length
+      (compute-insn-mask-lengths iflds)
+      (compute-insn-masks iflds)
+      insn))
 )
 
 ; Sformats.
@@ -327,19 +400,15 @@
 ; Sort IFLDS by dependencies and then by starting bit number.
 
 (define (-sfmt-order-iflds iflds)
-  (let ((up? 
-	 ; ??? Something like this is preferable.
-	 ;(not (ifld-lsb0? (car ifld-list)))
-	 (not (current-arch-insn-lsb0?))))
-    (let loop ((independent nil) (dependent nil) (iflds iflds))
-      (cond ((null? iflds)
-	     (append (sort-ifield-list independent up?)
-		     (sort-ifield-list dependent up?)))
-	    ; FIXME: quick hack.
-	    ((multi-ifield? (car iflds))
-	     (loop independent (cons (car iflds) dependent) (cdr iflds)))
-	    (else
-	     (loop (cons (car iflds) independent) dependent (cdr iflds))))))
+  (let loop ((independent nil) (dependent nil) (iflds iflds))
+    (cond ((null? iflds)
+	   (append (sort-ifield-list independent)
+		   (sort-ifield-list dependent)))
+	  ; FIXME: quick hack.
+	  ((multi-ifield? (car iflds))
+	   (loop independent (cons (car iflds) dependent) (cdr iflds)))
+	  (else
+	   (loop (cons (car iflds) independent) dependent (cdr iflds)))))
 )
 
 ; Return a sorted list of ifields used by IN-OPS, OUT-OPS.
@@ -407,21 +476,13 @@
 
 (define (ifmt-analyze insn compute-sformat?)
   ; First sort by starting bit number the list of fields in INSN.
-  (let ((sorted-ifields
-	 (sort-ifield-list (insn-iflds insn)
-			   ; ??? Something like this is preferable, but
-			   ; if the first insn is a virtual insn there are
-			   ; no fields.
-			   ;(not (ifld-lsb0? (car (insn-iflds insn))))
-			   (not (current-arch-insn-lsb0?))
-			   )))
+  (let ((sorted-ifields (insn-sorted-iflds insn)))
 
     (if (null? sorted-ifields)
 
 	; Field list is unspecified.
 	(list #f #f atlist-empty)
 
-	; FIXME: error checking (e.g. missing or overlapping bits)
 	(let* (; A list of the various bits of semantic code.
 	       (sems (list (insn-semantics insn)))
 	       ; Compute list of input and output operands if asked for.
@@ -434,20 +495,20 @@
 							   insn sems)
 					   atlist-empty))))
 	       )
+
 	  (let ((compiled-sems (csem-code sem-ops))
 		(in-ops (csem-inputs sem-ops))
 		(out-ops (csem-outputs sem-ops))
 		(attrs (csem-attrs sem-ops))
 		(cti? (or (atlist-cti? (csem-attrs sem-ops))
 			  (insn-cti? insn))))
-	    (list (make <fmt-desc>
-		    cti? sorted-ifields in-ops out-ops
-		    (if (and in-ops out-ops)
-			(-sfmt-used-iflds in-ops out-ops)
-			#f)
-		    attrs)
-		  compiled-sems
-		  attrs)))))
+	    (let ((ifmt-desc (make <fmt-desc>
+			       cti? sorted-ifields in-ops out-ops
+			       (if (and in-ops out-ops)
+				   (-sfmt-used-iflds in-ops out-ops)
+				   #f)
+			       attrs)))
+	      (list ifmt-desc compiled-sems attrs))))))
 )
 
 ; Subroutine of ifmt-compute!, to simplify it.
@@ -577,9 +638,9 @@
 			  -1 ; number
 			  #f ; key
 			  nil ; fields
-			  0 ; mask-length
 			  0 ; length
-			  0 ; mask
+			  '(0) ; mask-length
+			  '(0) ; mask
 			  #f)) ; eg-insn
 	 (empty-sfmt (make <sformat>
 			  'sfmt-empty
Index: cgen/insn.scm
===================================================================
RCS file: /cvs/src/src/cgen/insn.scm,v
retrieving revision 1.12
diff -u -p -r1.12 insn.scm
--- cgen/insn.scm	16 Jul 2003 05:35:47 -0000	1.12
+++ cgen/insn.scm	6 Aug 2003 17:43:14 -0000
@@ -19,7 +19,9 @@
 		; The insn fields as specified in the .cpu file.
 		; Also contains values for constant fields.
 		iflds
-		(iflds-values . #f) ; Lazily computed cache
+		(ifld-values . #f) ; lazily computed cache
+		(word-values . #f) ; lazily computed cache
+		(sorted-iflds . #f) ; lazily computed cache
 
 		; RTL source of assertions of ifield values or #f if none.
 		; This is used, for example, by the decoder to help
@@ -714,12 +716,12 @@
   (find (lambda (insn)
 	  (let* ((i-mask (insn-base-mask insn))
 		 (i-mask-len (insn-base-mask-length insn))
-		 (i-value (insn-value insn))
+		 (i-value (insn-base-value insn))
 		 (subset-insn (find-first 
 			       (lambda (insn2) ; insn2: possible submatch (more mask bits)
 				    (let ((i2-mask (insn-base-mask insn2))
 					  (i2-mask-len (insn-base-mask-length insn2))
-					  (i2-value (insn-value insn2)))
+					  (i2-value (insn-base-value insn2)))
 				      (and (not (eq? insn insn2))
 					   (= i-mask-len i2-mask-len)
 					   (mask-superset? i-mask i-value i2-mask i2-value))))
@@ -748,12 +750,12 @@
 (define (find-identical-insn insn insn-list)
   (let ((i-mask (insn-base-mask insn))
 	(i-mask-len (insn-base-mask-length insn))
-	(i-value (insn-value insn)))
+	(i-value (insn-base-value insn)))
     (find-first 
      (lambda (insn2)
        (let ((i2-mask (insn-base-mask insn2))
 	     (i2-mask-len (insn-base-mask-length insn2))
-	     (i2-value (insn-value insn2)))
+	     (i2-value (insn-base-value insn2)))
 	 (and (= i-mask-len i2-mask-len)
 	      (= i-mask i2-mask)
 	      (= i-value i2-value))))
@@ -815,40 +817,119 @@
 (define (insn-has-ifield? insn f-name)
   (->bool (object-assq f-name (insn-iflds insn)))
 )
+
+; Return sorted list of ifields.
+; The result is cached to speed up the next call.
+
+(define (insn-sorted-iflds insn)
+  (if (elm-get insn 'sorted-iflds)
+      (elm-get insn 'sorted-iflds)
+      (let ((flds (sort-ifield-list (insn-iflds insn))))
+	(elm-set! insn 'sorted-iflds flds)
+	flds))
+)
 
 ; Insn opcode value utilities.
 
+; Given INSN, return a sorted list of constant values (the opcode fields)
+; for each "word" in the insn, or #f if the ifield isn't constant.
+; NOTE: The order of elements in the result must be the same as the order of
+; ifields in the <iformat> spec, which is the sorted order.
+; The result is cached to speed up the next call.
+
+(define (insn-ifld-values insn)
+  (if (elm-get insn 'ifld-values)
+      (elm-get insn 'ifld-values)
+      (let ((values (map ifld-constant-value
+			 (sort-ifield-list
+			  (collect ifld-base-ifields (insn-iflds insn))))))
+	(elm-set! insn 'ifld-values values)
+	values)
+      )
+)
+
 ; Given INSN, return the length in bits of the base mask (insn-base-mask).
 
 (define (insn-base-mask-length insn)
-  (ifmt-mask-length (insn-ifmt insn))
+  (car (ifmt-mask-lengths (insn-ifmt insn)))
 )
 
 ; Given INSN, return the bitmask of constant values (the opcode field)
 ; in the base part.
 
 (define (insn-base-mask insn)
-  (ifmt-mask (insn-ifmt insn))
+  (car (ifmt-masks (insn-ifmt insn)))
 )
 
-; Given INSN, return the sum of the constant values in the insn
-; (i.e. the opcode field).
-;
-; See also (compute-insn-base-mask).
-;
-(define (insn-value insn)
-  (if (elm-get insn 'iflds-values)
-      (elm-get insn 'iflds-values)
-      (let* ((base-len (insn-base-mask-length insn))
-	     (value (apply +
-			   (map (lambda (fld) (ifld-value fld base-len (ifld-get-value fld)))
-				(find ifld-constant?
-				      (collect ifld-base-ifields (insn-iflds insn))))
-			   )))
-	(elm-set! insn 'iflds-values value)
-	value)
+; Given INSN, return the sum of the constant values in each word.
+; The result is cached to speed up the next call.
+
+(define (insn-word-values insn)
+  (if (elm-get insn 'word-values)
+
+      (elm-get insn 'word-values)
+
+      ; First sort the fields into bins of each "word".
+      (let* ((fld-list
+	      ; Have to resort the list in case of multi-ifields.
+	      (sort-ifield-list (collect ifld-real-ifields (insn-iflds insn))))
+	     (words (compute-insn-words fld-list))
+	     (bins (map (lambda (word) (cons word '())) words)))
+	(for-each (lambda (f)
+		    ; ??? Arguably not very efficient.  Optimize later.
+		    (let ((fword (-ifmt-ifield-word f)))
+		      (assoc-set! bins fword (cons f (assoc-ref bins fword)))))
+		  fld-list)
+
+	; Now compute the value of each word.
+	(let ((values (map (lambda (bin)
+			     (apply + (map (lambda (f)
+					     (ifld-value f #f #f))
+					   (find ifld-constant? (cdr bin)))))
+			   bins)))
+	  (elm-set! insn 'word-values values)
+	  values)
+	)
       )
-  )
+)
+
+; Given INSN, return the sum of the constant values in the base part of insn
+; (i.e. the opcode field).
+
+(define (insn-base-value insn)
+  (car (insn-word-values insn))
+)
+
+; Return index of word at OFFSET.
+
+(define (-insn-word-index insn offset)
+  (let* ((lengths (ifmt-mask-lengths (insn-ifmt insn)))
+	 (offsets (plus-scan (cons 0 lengths)))
+	 (search (memq offset offsets)))
+    (assert search)
+    (- (length offsets) (length search)))
+)
+
+; Return mask of word at OFFSET.
+
+(define (insn-mask-at-offset insn offset)
+  (let ((i (-insn-word-index insn offset)))
+    (list-ref (ifmt-masks (insn-ifmt insn)) i))
+)
+
+; Return length of word at OFFSET.
+
+(define (insn-mask-length-at-offset insn offset)
+  (let ((i (-insn-word-index insn offset)))
+    (list-ref (ifmt-mask-lengths (insn-ifmt insn)) i))
+)
+
+; Return value of word at OFFSET.
+
+(define (insn-value-at-offset insn offset)
+  (let ((i (-insn-word-index insn offset)))
+    (list-ref (insn-word-values insn) i))
+)
 
 ; Insn operand utilities.
 
Index: cgen/mach.scm
===================================================================
RCS file: /cvs/src/src/cgen/mach.scm,v
retrieving revision 1.7
diff -u -p -r1.7 mach.scm
--- cgen/mach.scm	16 Jul 2003 05:35:47 -0000	1.7
+++ cgen/mach.scm	6 Aug 2003 17:43:14 -0000
@@ -649,6 +649,12 @@
   *UNSPECIFIED*
 )
 
+; Return list of ISA names specified by ATLIST.
+
+(define (atlist-isa-list atlist)
+  (bitset-attr->list (atlist-attr-value atlist 'ISA #f))
+)
+
 ; Return list of ISA names specified by OBJ.
 
 (define (obj-isa-list obj)
@@ -663,6 +669,12 @@
 	(name (obj:name isa)))
     (->bool (memq name isas)))
 )
+
+; Return bitset attr value that indicates "all" isas.
+
+(define (attr-all-isas)
+  (stringize (current-arch-isa-name-list) ",")
+)
 
 ; The fetch/decode/execute process.
 ; "extract" is a fancy word for fetch/decode.
@@ -828,10 +840,7 @@
 		; and by the simulator's invalid insn handler.
 		default-insn-bitsize
 
-		; Number of bytes of insn that can be initially fetched.
-		; In non-LIW isas this would be the length of the smallest
-		; insn.  For LIW isas it depends - only one LIW isa is
-		; currently supported (m32r).
+		; Number of bits of insn that can be initially fetched.
 		base-insn-bitsize
 
 		; Initial bitnumbers to decode insns by.
@@ -954,7 +963,7 @@
 ; All arguments are in raw (non-evaluated) form.
 
 (define (-isa-parse context name comment attrs
-		    base-insn-bitsize default-insn-bitsize default-insn-word-bitsize
+		    default-insn-word-bitsize default-insn-bitsize base-insn-bitsize
 		    decode-assist liw-insns parallel-insns condition
 		    setup-semantics decode-splits)
   (logit 2 "Processing isa " name " ...\n")
@@ -1037,13 +1046,13 @@
 	      (loop (cdr arg-list)))))
       ; Now that we've identified the elements, build the object.
       (-isa-parse context name comment attrs
-		  base-insn-bitsize
 		  (if default-insn-word-bitsize
 		      default-insn-word-bitsize
 		      base-insn-bitsize)
 		  (if default-insn-bitsize
 		      default-insn-bitsize
 		      base-insn-bitsize)
+		  base-insn-bitsize
 		  decode-assist liw-insns parallel-insns- condition
 		  setup-semantics decode-splits)
       )
Index: cgen/model.scm
===================================================================
RCS file: /cvs/src/src/cgen/model.scm,v
retrieving revision 1.4
diff -u -p -r1.4 model.scm
--- cgen/model.scm	16 Jul 2003 05:35:47 -0000	1.4
+++ cgen/model.scm	6 Aug 2003 17:43:14 -0000
@@ -272,7 +272,7 @@
 ; are returned as (model1), i.e. an empty unit list.
 
 (define (parse-insn-timing context insn-timing-desc)
-  (logit 2 "parse-insn-timing: context==" context ", desc==" insn-timing-desc "\n")
+  (logit 3 "parse-insn-timing: context " context ", desc " insn-timing-desc "\n")
   (map (lambda (model-timing-desc)
 	 (let* ((model-name (car model-timing-desc))
 		(model (current-model-lookup model-name)))
Index: cgen/opc-itab.scm
===================================================================
RCS file: /cvs/src/src/cgen/opc-itab.scm,v
retrieving revision 1.10
diff -u -p -r1.10 opc-itab.scm
--- cgen/opc-itab.scm	16 Jul 2003 05:35:47 -0000	1.10
+++ cgen/opc-itab.scm	6 Aug 2003 17:43:15 -0000
@@ -196,7 +196,7 @@
 
 ; Instruction format table support.
 
-; Return the table for IFMT, an <iformat> object.
+; Return the CGEN_IFMT table for <iformat> IFMT.
 
 (define (-gen-ifmt-table-1 ifmt)
   (gen-obj-sanitize
@@ -204,10 +204,19 @@
    (string-list
     "static const CGEN_IFMT " (gen-sym ifmt) " = {\n"
     "  "
-    (number->string (ifmt-mask-length ifmt)) ", "
     (number->string (ifmt-length ifmt)) ", "
-    "0x" (number->string (ifmt-mask ifmt) 16) ", "
+    (number->string (length (ifmt-mask-lengths ifmt))) ", "
     "{ "
+    (string-drop 2
+		 (string-map (lambda (ml)
+			       (string-append ", " (number->string ml)))
+			     (ifmt-mask-lengths ifmt)))
+    " }, { "
+    (string-drop 2
+		 (string-map (lambda (m)
+			       (string-append ", 0x" (number->string m 16)))
+			     (ifmt-masks ifmt)))
+    " }, { "
     (string-list-map (lambda (ifld)
 		       (string-list "{ F (" (ifld-enum ifld #f) ") }, "))
 		     (ifmt-ifields ifmt))
@@ -220,6 +229,7 @@
   (string-write
    "/* Instruction formats.  */\n\n"
    (gen-define-with-symcat "F(f) & @arch@_cgen_ifld_table[@ARCH@_" "f]")
+   "\n"
    (string-list-map -gen-ifmt-table-1 (current-ifmt-list))
    "#undef F\n\n"
    )
@@ -317,17 +327,28 @@
   (string-append "& " (gen-sym (insn-ifmt insn)))
 )
 
-; Return the definition of an instruction value entry.
+; Return the definition of a CGEN_IVALUE entry.
 
 (define (gen-ivalue-entry insn)
-  (string-list "{ "
-	       "0x" (number->string (insn-value insn) 16)
-	       (if #f ; (ifmt-opcodes-beyond-base? (insn-ifmt insn))
-		   (string-list ", { "
-				; ??? wip: opcode values beyond the base insn
-				"0 }")
-		   "")
-	       " }")
+  (let ((word-values (insn-word-values insn))
+	(ifld-values (insn-ifld-values insn)))
+    (string-list
+     "{ { "
+     (string-drop 2
+		  (string-map (lambda (v)
+				(string-append ", 0x" (number->string v 16)))
+			      word-values))
+     " }, "
+     "0x" (number->string (bits->integer (bools->bits (reverse ifld-values)))
+			  16)
+     ", { "
+     (string-drop 2
+		  (string-map (lambda (v)
+				(if v
+				    (string-append ", 0x" (number->string v 16))
+				    ", 0"))
+			      ifld-values))
+     " } }"))
 )
 
 ; Generate an insn opcode entry for INSN.
@@ -342,10 +363,8 @@
     "  {\n"
     "    " (gen-insn-handlers insn) ",\n"
     "    " (gen-syntax-entry "MNEM" "OP" (insn-syntax insn)) ",\n"
-    ; ??? 'twould save space to put a pointer here and record format separately
-    "    " (gen-ifmt-entry insn) ", "
-    ;"0x" (number->string (insn-value insn) 16) ",\n"
-    (gen-ivalue-entry insn) "\n"
+    "    " (gen-ifmt-entry insn) ",\n"
+    "    " (gen-ivalue-entry insn) "\n"
     "  },\n"))
 )
 
@@ -369,7 +388,7 @@ static const CGEN_OPCODE @arch@_cgen_ins
   /* Special null first entry.
      A `num' value of zero is thus invalid.
      Also, the special `invalid' insn resides here.  */
-  { { 0, 0, 0, 0 }, {{0}}, 0, {0}},\n"
+  { { 0, 0, 0, 0 }, {{0}}, NULL, { {0}, 0, {0} } },\n"
 
      (lambda ()
        (string-write-map (lambda (insn)
Index: cgen/opc-opinst.scm
===================================================================
RCS file: /cvs/src/src/cgen/opc-opinst.scm,v
retrieving revision 1.3
diff -u -p -r1.3 opc-opinst.scm
--- cgen/opc-opinst.scm	15 May 2003 07:25:02 -0000	1.3
+++ cgen/opc-opinst.scm	6 Aug 2003 17:43:15 -0000
@@ -54,7 +54,7 @@
 		  ins)
       (string-map (lambda (op)  (-gen-operand-instance op "OUTPUT"))
 		  outs)
-      "  { END }\n};\n\n")))
+      "  { END, 0, 0, 0, 0, 0, 0 /*-Wall*/ }\n};\n\n")))
 )
 
 (define (-gen-operand-instance-tables)
Index: cgen/opcodes.scm
===================================================================
RCS file: /cvs/src/src/cgen/opcodes.scm,v
retrieving revision 1.6
diff -u -p -r1.6 opcodes.scm
--- cgen/opcodes.scm	16 Jul 2003 05:35:47 -0000	1.6
+++ cgen/opcodes.scm	6 Aug 2003 17:43:15 -0000
@@ -205,6 +205,7 @@
      (string-list
       "      {\n"
       (if need-extra?
+	  ; FIXME: We shouldn't be modifying `ifields' here.
 	  (string-append "        " varname " = "
 			 (let ((expr (cadr encode))
 			       (value (caar encode))
@@ -268,7 +269,6 @@
       )))
 )
 
-
 (method-make!
  <derived-operand> 'gen-extract
  (lambda (self operand)
@@ -289,7 +289,6 @@
 ;    "      }\n"
 ;    ))
 ;)
-
 
 ; Hardware index support code.
 
@@ -615,7 +614,6 @@
    "      abort();\n") ; should never be called
 )
 
-
 ; Need to call op:type to resolve the hardware reference.
 ;(method-make-forward! <operand> 'type '(gen-parse gen-print))
 
@@ -645,7 +643,6 @@
 
 (method-make-forward! <operand> 'index '(gen-insert gen-extract))
 ; But: <derived-operand> has its own gen-insert / gen-extract.
-
 
 ; Return the value of PC.
 ; Used by insert/extract fields.
Index: cgen/pgmr-tools.scm
===================================================================
RCS file: /cvs/src/src/cgen/pgmr-tools.scm,v
retrieving revision 1.2
diff -u -p -r1.2 pgmr-tools.scm
--- cgen/pgmr-tools.scm	16 Jul 2003 05:35:47 -0000	1.2
+++ cgen/pgmr-tools.scm	6 Aug 2003 17:43:15 -0000
@@ -32,6 +32,8 @@
 
 ; Pretty print the instruction's opcode value, for debugging.
 ; INSN is an <insn> object.
+;
+; FIXME: Rewrite to print all masks, not just base-mask.
 
 (define (pgmr-pretty-print-insn-format insn)
 
@@ -85,10 +87,9 @@
 		   (number->string (ifld-length f))
 		   "\n"))
 
-  (let* ((iflds (sort-ifield-list (insn-iflds insn)
-				  (not (current-arch-insn-lsb0?))))
-	 (mask (compute-insn-base-mask iflds))
-	 (mask-length (compute-insn-base-mask-length iflds)))
+  (let* ((iflds (insn-sorted-iflds insn))
+	 (mask-lengths (compute-insn-mask-lengths iflds))
+	 (masks (compute-insn-masks iflds)))
 
     (display
      (string-append
@@ -103,15 +104,15 @@
       (number->string (apply + (map ifld-length iflds)))
       "\n"
       "Mask:  "
-      (dump-insn-mask mask mask-length)
+      (dump-insn-mask (car masks) (car mask-lengths))
       "\n"
       "Value: "
       (let ((value (apply +
 			  (map (lambda (fld)
-				 (ifld-value fld mask-length
+				 (ifld-value fld (car mask-lengths)
 					     (ifld-get-value fld)))
 			       (find ifld-constant? (collect ifld-base-ifields (insn-iflds insn)))))))
-	(dump-insn-value value mask mask-length))
+	(dump-insn-value value (car masks) (car mask-lengths)))
       ; TODO: Print value spaced according to fields.
       "\n"
       )))
@@ -154,6 +155,8 @@
 ; VALUE is either a single number of size base-insn-bitsize,
 ; or a list of numbers for variable length ISAs.
 ; LENGTH is the total length of VALUE in bits.
+;
+; FIXME: list VALUE not fully handled methinks
 
 (define (pgmr-lookup-insn length value)
   (arch-analyze-insns! CURRENT-ARCH
@@ -162,8 +165,8 @@
 
   ; Return a boolean indicating if BASE matches the base part of <insn> INSN.
   (define (match-base base insn)
-    (let ((mask (compute-insn-base-mask (insn-iflds insn)))
-	  (ivalue (insn-value insn)))
+    (let ((mask (insn-base-mask insn))
+	  (ivalue (insn-base-value insn)))
       ; return (value & mask) == ivalue
       (= (logand base mask) ivalue)))
 
Index: cgen/rtl-c.scm
===================================================================
RCS file: /cvs/src/src/cgen/rtl-c.scm,v
retrieving revision 1.5
diff -u -p -r1.5 rtl-c.scm
--- cgen/rtl-c.scm	16 Jul 2003 05:35:47 -0000	1.5
+++ cgen/rtl-c.scm	6 Aug 2003 17:43:16 -0000
@@ -742,6 +742,10 @@
 	(cx:make mode ; not sem-mode on purpose
 		 (string-append "("
 				; Ensure correct sign of shift.
+				; FIXME: This doesn't do enough to ensure the
+				; correct sign is used.  Have a utility to
+				; compute the correct cast given the mode and
+				; signed/unsigned indicator.
 				(cond ((equal? name "SRL")
 				       (string-append "("
 						      (if (eq? (mode:class mode) 'UINT)
@@ -1272,12 +1276,13 @@
 ; Instruction field support.
 ; ??? This should build an operand object like -build-ifield-operand! does
 ; in semantics.scm.
-; ??? Mode support is wip.
 
 (define-fn ifield (estate options mode ifld-name)
-  (if (estate-ifield-var? estate)
-      (cx:make 'UINT (gen-c-symbol ifld-name))
-      (cx:make 'UINT (string-append "FLD (" (gen-c-symbol ifld-name) ")")))
+  (let* ((f (current-ifld-lookup ifld-name))
+	 (mode-name (obj:name (ifld-mode f))))
+    (if (estate-ifield-var? estate)
+	(cx:make mode-name (gen-c-symbol ifld-name))
+	(cx:make mode-name (string-append "FLD (" (gen-c-symbol ifld-name) ")"))))
 ;  (let ((f (current-ifld-lookup ifld-name)))
 ;    (make <operand> ifld-name ifld-name
 ;	  (atlist-cons (bool-attr-make 'SEM-ONLY #t)
Index: cgen/sid-decode.scm
===================================================================
RCS file: /cvs/src/src/cgen/sid-decode.scm,v
retrieving revision 1.12
diff -u -p -r1.12 sid-decode.scm
--- cgen/sid-decode.scm	8 Jul 2003 16:19:35 -0000	1.12
+++ cgen/sid-decode.scm	6 Aug 2003 17:43:17 -0000
@@ -614,35 +614,33 @@ static void
 
 ; Generate top level decoder.
 ; INITIAL-BITNUMS is a target supplied list of bit numbers to use to
-; build the first decode table.  If nil, we compute 8 bits of it (FIXME)
-; ourselves.
+; build the first decode table.  If nil, we compute 8 bits of it ourselves.
 ; LSB0? is non-#f if bit number 0 is the least significant bit.
 
 (define (-gen-decode-fn insn-list initial-bitnums lsb0?)
   (assert (with-scache?))
 
-  ; Compute the initial DECODE-BITSIZE as the minimum of all insn lengths.
-  ; The caller of @prefix@_decode must fetch and pass exactly this number of bits
-  ; of the instruction.
-  ; ??? Make this a parameter later but only if necessary.
+  ; Start decoding with the base insn word.
+  ; The caller of @prefix@_decode must fetch and pass exactly this number of
+  ; bits of the instruction.
 
-  (let ((decode-bitsize (state-base-insn-bitsize)))
+  (let ((decode-word-offset 0)
+	(decode-word-bitsize (state-base-insn-bitsize)))
 
     ; Compute INITIAL-BITNUMS if not supplied.
-    ; 0 is passed for the start bit (it is independent of lsb0?)
     (if (null? initial-bitnums)
 	(set! initial-bitnums
 	      (if (= 0 (length insn-list))
 		  (list 0) ; dummy value
 		  (decode-get-best-bits insn-list nil
-					0 ; startbit
 					8 ; max
-					decode-bitsize
+					decode-word-offset
+					decode-word-bitsize
 					lsb0?))))
 	
     ; All set.  gen-decoder does the hard part, we just print out the result. 
     (let ((decode-code (gen-decoder insn-list initial-bitnums
-				    decode-bitsize
+				    decode-word-bitsize
 				    "    " lsb0?
 				    (current-insn-lookup 'x-invalid)
 				    #t)))
Index: cgen/sim-decode.scm
===================================================================
RCS file: /cvs/src/src/cgen/sim-decode.scm,v
retrieving revision 1.9
diff -u -p -r1.9 sim-decode.scm
--- cgen/sim-decode.scm	8 Jul 2003 16:19:35 -0000	1.9
+++ cgen/sim-decode.scm	6 Aug 2003 17:43:17 -0000
@@ -463,31 +463,29 @@ void
 
 ; Generate top level decoder.
 ; INITIAL-BITNUMS is a target supplied list of bit numbers to use to
-; build the first decode table.  If nil, we compute 8 bits of it (FIXME)
-; ourselves.
+; build the first decode table.  If nil, we compute 8 bits of it ourselves.
 ; LSB0? is non-#f if bit number 0 is the least significant bit.
 
 (define (-gen-decode-fn insn-list initial-bitnums lsb0?)
 
-  ; Compute the initial DECODE-BITSIZE as the minimum of all insn lengths.
-  ; The caller of @prefix@_decode must fetch and pass exactly this number of bits
-  ; of the instruction.
-  ; ??? Make this a parameter later but only if necessary.
+  ; Start decoding with the base insn word.
+  ; The caller of @prefix@_decode must fetch and pass exactly this number of
+  ; bits of the instruction.
 
-  (let ((decode-bitsize (apply min (map insn-base-mask-length insn-list))))
+  (let ((decode-word-offset 0)
+	(decode-word-bitsize (state-base-insn-bitsize)))
 
     ; Compute INITIAL-BITNUMS if not supplied.
-    ; 0 is passed for the start bit (it is independent of lsb0?)
     (if (null? initial-bitnums)
 	(set! initial-bitnums (decode-get-best-bits insn-list nil
-						    0 ; startbit
 						    8 ; max
-						    decode-bitsize
+						    decode-word-offset
+						    decode-word-bitsize
 						    lsb0?)))
 
     ; All set.  gen-decoder does the hard part, we just print out the result. 
     (let ((decode-code (gen-decoder insn-list initial-bitnums
-				    decode-bitsize
+				    decode-word-bitsize
 				    "    " lsb0?
 				    (current-insn-lookup 'x-invalid)
 				    #f)))
Index: cgen/utils-sim.scm
===================================================================
RCS file: /cvs/src/src/cgen/utils-sim.scm,v
retrieving revision 1.12
diff -u -p -r1.12 utils-sim.scm
--- cgen/utils-sim.scm	16 Jul 2003 05:35:48 -0000	1.12
+++ cgen/utils-sim.scm	6 Aug 2003 17:43:17 -0000
@@ -519,13 +519,13 @@
 ; treat as bitnum 0.
 ; BITNUMS must be monotonically increasing.
 ; LSB0? is non-#f if bit number 0 is the least significant bit.
-; FIXME: START may not be handled right in words beyond first.
 ;
-; e.g. (-gen-decode-bits '(0 1 2 3 8 9 10 11) 0 16 "insn" #f)
+; e.g. (-gen-decode-bits '(0 1 2 3 8 9 10 11) 16 "insn" #f)
 ; --> "(((insn >> 8) & 0xf0) | ((insn >> 4) & 0xf))"
+;
 ; FIXME: The generated code has some inefficiencies in edge cases.  Later.
 
-(define (-gen-decode-bits bitnums start size val lsb0?)
+(define (-gen-decode-bits bitnums size val lsb0?)
 
   ; Compute a list of lists of three numbers:
   ; (first bitnum in group, position in result (0=LSB), bits in result)
@@ -566,7 +566,7 @@
 			    ; FIXME: Need to handle left (-ve) shift.
 			    (shift (- (if lsb0?
 					  (- first bits -1)
-					  (- (+ start size) (+ first bits)))
+					  (- size (+ first bits)))
 				      pos)))
 		     (string-append
 		      " | ((" val " >> " (number->string shift)
@@ -924,7 +924,8 @@
 ; else {}
 ; may well be less stressful on the compiler to optimize than small switch() stmts.
 
-(define (-gen-decoder-switch switch-num startbit decode-bitsize table-guts indent lsb0? invalid-insn fn?)
+(define (-gen-decoder-switch switch-num startbit decode-bitsize table-guts
+			     indent lsb0? invalid-insn fn?)
   ; For entries that are a single insn, we're done, otherwise recurse.
 
   (string-list
@@ -943,7 +944,7 @@
 			indent "  val = "))
        (string-append indent "  unsigned int val = "))
    (-gen-decode-bits (dtable-guts-bitnums table-guts)
-		     (dtable-guts-startbit table-guts)
+		     ;(dtable-guts-startbit table-guts)
 		     (dtable-guts-bitsize table-guts) "insn" lsb0?)
    ";\n"
    indent "  switch (val)\n"
@@ -990,12 +991,14 @@
 ; Decoder generation entry point.
 ; Generate code to decode INSN-LIST.
 ; BITNUMS is the set of bits to initially key off of.
-; DECODE-BITSIZE is the number of bits of the instruction that `insn' holds.
+; DECODE-BITSIZE is the number of bits of the instruction that C variable
+; `insn' holds.  Basically, it's the base insn size.
 ; LSB0? is non-#f if bit number 0 is the least significant bit.
 ; INVALID-INSN is the <insn> object of the pseudo insn to handle invalid ones.
 ; FN? is non-#f if the extractors are functions rather than inline code
 
-(define (gen-decoder insn-list bitnums decode-bitsize indent lsb0? invalid-insn fn?)
+(define (gen-decoder insn-list bitnums decode-bitsize
+		     indent lsb0? invalid-insn fn?)
   (logit 3 "Building decode tree.\n"
 	 "bitnums = " (stringize bitnums " ") "\n"
 	 "decode-bitsize = " (number->string decode-bitsize) "\n"
Index: cgen/utils.scm
===================================================================
RCS file: /cvs/src/src/cgen/utils.scm,v
retrieving revision 1.11
diff -u -p -r1.11 utils.scm
--- cgen/utils.scm	16 Jul 2003 05:35:48 -0000	1.11
+++ cgen/utils.scm	6 Aug 2003 17:43:18 -0000
@@ -870,6 +870,15 @@
       (logbit? bit-num n))
 )
 
+; Convert a list of 1's and 0's to the integer value.
+; Example: (1 0 1) -> 5.
+
+(define (bits->integer bits)
+  (let ((powers (powers-of-2 (length bits))))
+    (apply + (map (lambda (bit p) (if (= bit 0) 0 p))
+		  bits powers)))
+)
+
 ; Return #t if each element of bools is #t.  Since Scheme considers any
 ; non-#f value as #t we do too.
 ; (all-true? '()) is #t since that is the identity element.
@@ -908,8 +917,9 @@
 	(loop (+ result (remainder bits 2)) (quotient bits 2))))
 )
 
-; Convert bits in N #f/#t.
+; Convert bits in N to #f/#t.
 ; LENGTH is the length of N in bits.
+; FIXME: Rename, "bits" as come to mean list of bits.
 
 (define (bits->bools n length)
   (do ((result (make-list length #f))
@@ -917,6 +927,18 @@
       ((= i length) (reverse! result))
     (list-set! result i (if (bit-set? n i) #t #f))
     )
+)
+
+; Convert #f/non-#f to 0/1.
+
+(define (bool->bit bool)
+  (if bool 1 0)
+)
+
+; Convert list of #f/non-#f to 0/1.
+
+(define (bools->bits bools)
+  (map bool->bit bools)
 )
 
 ; Print a C integer.
Index: cgen/cpu/m32r.cpu
===================================================================
RCS file: /cvs/src/src/cgen/cpu/m32r.cpu,v
retrieving revision 1.4
diff -u -p -r1.4 m32r.cpu
--- cgen/cpu/m32r.cpu	16 Jul 2003 05:35:48 -0000	1.4
+++ cgen/cpu/m32r.cpu	6 Aug 2003 17:43:19 -0000
@@ -55,20 +55,12 @@
   ; on a 16 bit (and not 32 bit) boundary, will only want to advance pc by 16.)
   (default-insn-bitsize 32)
 
-  ; Number of bytes of insn we can initially fetch.
-  ; The M32R is tricky in that insns are either two 16-bit insns
-  ; (executed sequentially or in parallel) or one 32-bit insn.
-  ; So on one hand the base insn size is 16 bits, but on another it's 32.
-  ; 32 is chosen because:
-  ; - if the chip were ever bi-endian it is believed that the byte order would
-  ;   be based on 32 bit quantities
-  ; - 32 bit insns are always aligned on 32 bit boundaries
-  ; - the pc will never stop on a 16 bit (and not 32 bit) boundary
-  ;   [well actually it can, but there are no branches to such places]
-  (base-insn-bitsize 32)
+  ; Number of bytes of insn we can initially fetch to decode an insn.
+  (base-insn-bitsize 16)
 
-  ; Used in computing bit numbers.
-  (default-insn-word-bitsize 32)
+  ; Used in computing bit numbers and ifield word lengths for
+  ; fields that don't specify it.
+  (default-insn-word-bitsize 16)
 
   ; The m32r fetches 2 insns at a time.
   (liw-insns 2)
@@ -382,7 +374,24 @@
 (dnf f-uimm4     "uimm4"               () 12 4)
 (dnf f-uimm5     "uimm5"               () 11 5)
 (dnf f-uimm16    "uimm16"              () 16 16)
-(dnf f-uimm24    "uimm24"              (ABS-ADDR RELOC) 8 24)
+
+; f-uimm24 is split into two because it's always used with f-op1 which is
+; in a 16 bit word, leaving only another 16 bits for the full insn.
+;(dnf f-uimm24    "uimm24"              (ABS-ADDR RELOC) 8 24)
+(dnf f-uimm24hi  "uimm24hi"            () 8 8)
+(dnf f-uimm24lo  "uimm24lo"            () 16 16)
+(dnmf f-uimm24   "uimm24"              (ABS-ADDR RELOC) UINT
+      (f-uimm24hi f-uimm24lo)
+      (sequence () ; insert
+		(set (ifield f-uimm24hi) (srl (ifield f-uimm24) (const 16)))
+		(set (ifield f-uimm24lo) (and (ifield f-uimm24) (const #xffff)))
+		)
+      (sequence () ; extract
+		(set (ifield f-uimm24) (or (sll (ifield f-uimm24hi) (const 16))
+					   (ifield f-uimm24lo)))
+		)
+)
+
 (dnf f-hi16      "high 16 bits"        (SIGN-OPT) 16 16)
 (df f-disp8      "disp8, slot unknown" (PCREL-ADDR RELOC) 8 8 INT
     ((value pc) (sra WI (sub WI value (and WI pc (const -4))) (const 2)))
@@ -390,9 +399,27 @@
 (df f-disp16     "disp16"              (PCREL-ADDR RELOC) 16 16 INT
     ((value pc) (sra WI (sub WI value pc) (const 2)))
     ((value pc) (add WI (sll WI value (const 2)) pc)))
-(df f-disp24     "disp24"              (PCREL-ADDR RELOC) 8 24 INT
-    ((value pc) (sra WI (sub WI value pc) (const 2)))
-    ((value pc) (add WI (sll WI value (const 2)) pc)))
+
+; f-disp24 is split into two because it's always used with f-op1 which is
+; in a 16 bit word, leaving only another 16 bits for the full insn.
+;(df f-disp24     "disp24"              (PCREL-ADDR RELOC) 8 24 INT
+;    ((value pc) (sra WI (sub WI value pc) (const 2)))
+;    ((value pc) (add WI (sll WI value (const 2)) pc)))
+(df f-disp24hi   "disp24hi"            () 8 8 INT #f #f)
+(df f-disp24lo   "disp24lo"            () 16 16 UINT #f #f)
+(dfmf f-disp24   "disp24"              (PCREL-ADDR RELOC) INT
+      (f-disp24hi f-disp24lo)
+      (sequence () ; insert
+		(set (ifield f-disp24hi) (sra (ifield f-disp24) (const 16)))
+		(set (ifield f-disp24lo) (and (ifield f-disp24) (const #xffff)))
+		)
+      (sequence () ; extract
+		(set (ifield f-disp24) (or (sll (ifield f-disp24hi) (const 16))
+					   (ifield f-disp24lo)))
+		)
+    ((value pc) (sra WI (sub WI value pc) (const 2))) ; encode
+    ((value pc) (add WI (sll WI value (const 2)) pc)) ; decode
+)
 
 (dnf f-op23      "op2.3"               ()  9 3)
 (dnf f-op3       "op3"                 () 14 2)
Index: cgen/cpu/m32r.opc
===================================================================
RCS file: /cvs/src/src/cgen/cpu/m32r.opc,v
retrieving revision 1.3
diff -u -p -r1.3 m32r.opc
--- cgen/cpu/m32r.opc	20 Nov 2001 05:16:06 -0000	1.3
+++ cgen/cpu/m32r.opc	6 Aug 2003 17:43:19 -0000
@@ -243,9 +243,10 @@ my_print_insn (cd, pc, info)
       return -1;
     }
 
-  /* 32 bit insn?  */
+  /* 32 bit insn?
+     Pass 2 for buflen because that's base-insn-bitsize.  */
   if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
-    return print_insn (cd, pc, info, buf, buflen);
+    return print_insn (cd, pc, info, buf, 2);
 
   /* Print the first insn.  */
   if ((pc & 3) == 0)
Index: cgen/cpu/simplify.inc
===================================================================
RCS file: /cvs/src/src/cgen/cpu/simplify.inc,v
retrieving revision 1.1
diff -u -p -r1.1 simplify.inc
--- cgen/cpu/simplify.inc	5 Jul 2001 12:45:47 -0000	1.1
+++ cgen/cpu/simplify.inc	6 Aug 2003 17:43:19 -0000
@@ -45,13 +45,20 @@ Define a normal instruction opcode enum.
   define-normal-ifield
 )
 
+; For those who don't like typing.
+
+(define-pmacro dfmf
+  "Shorthand form of define-full-multi-ifield.\n"
+  define-full-multi-ifield
+)
+
 ; Define a normal multi-ifield.
 ; FIXME: The define-normal version for ifields doesn't include the mode.
 
 (define-pmacro (define-normal-multi-ifield name comment attrs
 		 mode subflds insert extract)
   "Define a normal multi-part instruction field.\n"
-  (define-full-multi-ifield name comment attrs mode subflds insert extract)
+  (define-full-multi-ifield name comment attrs mode subflds insert extract #f #f)
 )
 
 ; For those who don't like typing.
@@ -65,7 +72,7 @@ Define a normal instruction opcode enum.
 
 (define-pmacro (dsmf name comment attrs subflds)
   "Define a simple multi-part instruction field.\n"
-  (define-full-multi-ifield name comment attrs UINT subflds #f #f)
+  (define-full-multi-ifield name comment attrs UINT subflds #f #f #f #f)
 )
 
 ; Hardware.
Index: cgen/cpu/xstormy16.cpu
===================================================================
RCS file: /cvs/src/src/cgen/cpu/xstormy16.cpu,v
retrieving revision 1.11
diff -u -p -r1.11 xstormy16.cpu
--- cgen/cpu/xstormy16.cpu	10 Jun 2003 21:22:04 -0000	1.11
+++ cgen/cpu/xstormy16.cpu	6 Aug 2003 17:43:19 -0000
@@ -16,12 +16,9 @@
 (define-isa
   (name xstormy16)
   (comment "Xstormy16 instruction set")
-  (default-insn-word-bitsize 32)
-  (default-insn-bitsize 32)
-  ; FIXME base-insn-bitsize should be 16 too, but at present CGEN has
-  ; no support for instruction sets with opcode bits past
-  ; base-insn-bitsize, so we must set it to at least 20.
-  (base-insn-bitsize 32)
+  (default-insn-word-bitsize 16)
+  (default-insn-bitsize 16)
+  (base-insn-bitsize 16)
 )
 
 (define-cpu
? include/opcode/foo
Index: include/opcode/cgen.h
===================================================================
RCS file: /cvs/src/src/include/opcode/cgen.h,v
retrieving revision 1.18
diff -u -p -r1.18 cgen.h
--- include/opcode/cgen.h	2 Dec 2002 21:51:52 -0000	1.18
+++ include/opcode/cgen.h	6 Aug 2003 17:43:22 -0000
@@ -250,6 +250,13 @@ typedef struct {
   /* Mask of bytes that are valid in INSN_BYTES.  */
   unsigned int valid;
 } CGEN_EXTRACT_INFO;
+
+extern int cgen_fill_opcode_cache
+#ifdef __BFD_H_SEEN__
+     PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int offset, int bytes, bfd_vma pc));
+#else
+     ();
+#endif
 
 /* Associated with each insn or expression is a set of "handlers" for
    performing operations like parsing, printing, etc.  These require a bfd_vma
@@ -864,10 +871,12 @@ typedef struct {
 #define CGEN_IFMT_IFLD_IFLD(ii) ((ii)->ifld)
 } CGEN_IFMT_IFLD;
 
-/* This should be at least as large as necessary for any target. */
+/* This should be at least as large as necessary for any target.
+   It's done this way so that the tables are usable by target-independent
+   code.  */
 #define CGEN_MAX_IFMT_OPERANDS 16
 
-/* A target may know its own precise maximum.  Assert that it falls below
+/* Assert that the target's number of ifmt operands falls below
    the above limit. */
 #ifdef CGEN_ACTUAL_MAX_IFMT_OPERANDS
 #if CGEN_ACTUAL_MAX_IFMT_OPERANDS > CGEN_MAX_IFMT_OPERANDS
@@ -875,27 +884,44 @@ typedef struct {
 #endif
 #endif
 
+/* This should be at least as large as necessary for any target.
+   It's done this way so that the tables are usable by target-independent
+   code.  */
+#define CGEN_MAX_INSN_WORDS 8
+
+/* Assert that the target's number of mask lengths falls below
+   the above limit. */
+#ifdef CGEN_ACTUAL_MAX_INSN_WORDS
+#if CGEN_ACTUAL_MAX_INSN_WORDS > CGEN_MAX_INSN_WORDS
+#error "CGEN_ACTUAL_MAX_INSN_WORDS too high - enlarge CGEN_MAX_INSN_WORDS"
+#endif
+#endif
 
 typedef struct
 {
-  /* Length that MASK and VALUE have been calculated to
-     [VALUE is recorded elsewhere].
-     Normally it is base_insn_bitsize.  On [V]LIW architectures where the base
-     insn size may be larger than the size of an insn, this field is less than
-     base_insn_bitsize.  */
-  unsigned char mask_length;
-#define CGEN_IFMT_MASK_LENGTH(ifmt) ((ifmt)->mask_length)
-
   /* Total length of instruction, in bits.  */
   unsigned char length;
 #define CGEN_IFMT_LENGTH(ifmt) ((ifmt)->length)
 
-  /* Mask to apply to the first MASK_LENGTH bits.
+  /* # entries in mask_lengths, etc.
+     NOTE: "words" here is a misnomer but I can't think of a better one.
+     Not all words in an insn are the same size.  For example, an insn with a
+     16 bit opcode and a 32 bit immediate might have 2 words: 16 and 32 bits.  */
+  unsigned char num_words;
+#define CGEN_IFMT_NUM_WORDS(ifmt) ((ifmt)->num_words)
+
+  /* Length that each mask and value have been calculated to
+     [values are recorded elsewhere].
+     The first element is base_insn_bitsize.  */
+  unsigned char word_lengths[CGEN_MAX_INSN_WORDS];
+#define CGEN_IFMT_WORD_LENGTH(ifmt,i) ((ifmt)->word_lengths[i])
+
+  /* Mask to apply to the mask_lengths[i] bits.
      Each insn's value is stored with the insn.
      The first step in recognizing an insn for disassembly is
-     (opcode & mask) == value.  */
-  CGEN_INSN_INT mask;
-#define CGEN_IFMT_MASK(ifmt) ((ifmt)->mask)
+     (opcode & masks[0]) == values[0].  */
+  CGEN_INSN_INT masks[CGEN_MAX_INSN_WORDS];
+#define CGEN_IFMT_MASK(ifmt,i) ((ifmt)->masks[i])
 
   /* Instruction fields.
      +1 for trailing NULL.  */
@@ -903,17 +929,29 @@ typedef struct
 #define CGEN_IFMT_IFLDS(ifmt) ((ifmt)->iflds)
 } CGEN_IFMT;
 
-/* Instruction values.  */
+/* Instruction values.
+   Specifying the value in two different ways is intentional.
+   Different clients want the data in different ways.  */
 
 typedef struct
 {
-  /* The opcode portion of the base insn.  */
-  CGEN_INSN_INT base_value;
-
-#ifdef CGEN_MAX_EXTRA_OPCODE_OPERANDS
-  /* Extra opcode values beyond base_value.  */
-  unsigned long ifield_values[CGEN_MAX_EXTRA_OPCODE_OPERANDS];
-#endif
+  /* The constant portion of the insn.
+     There is a 1-1 correspondence between these values and
+     CGEN_IFMT.masks.  */
+  /* FIXME: The name opcodes is overused here.  */
+  CGEN_INSN_INT opcodes[CGEN_MAX_INSN_WORDS];
+#define CGEN_IVALUE_OPCODE(iv,i) ((iv)->opcodes[i])
+
+  /* Mask of valid entries in ifields.  */
+  unsigned valid_ifields;
+#define CGEN_IVALUE_VALID_IFIELD(iv,i) \
+  (((iv)->valid_ifields & (1 << (i))) != 0)
+
+  /* Extra opcode values beyond base_value.
+     There is a 1-1 correspondence between these values and
+     CGEN_IFMT.iflds.  */
+  CGEN_INSN_INT ifields[CGEN_MAX_IFMT_OPERANDS];
+#define CGEN_IVALUE_IFIELD(iv,i) ((iv)->ifields[i])
 } CGEN_IVALUE;
 
 /* Instruction opcode table.
@@ -937,15 +975,13 @@ typedef struct
   /* Format entry.  */
   const CGEN_IFMT *format;
 #define CGEN_OPCODE_FORMAT(opc) ((opc)->format)
-#define CGEN_OPCODE_MASK_BITSIZE(opc) CGEN_IFMT_MASK_LENGTH (CGEN_OPCODE_FORMAT (opc))
-#define CGEN_OPCODE_BITSIZE(opc) CGEN_IFMT_LENGTH (CGEN_OPCODE_FORMAT (opc))
-#define CGEN_OPCODE_IFLDS(opc) CGEN_IFMT_IFLDS (CGEN_OPCODE_FORMAT (opc))
 
   /* Instruction opcode value.  */
-  CGEN_IVALUE value;
-#define CGEN_OPCODE_VALUE(opc) (& (opc)->value)
-#define CGEN_OPCODE_BASE_VALUE(opc) (CGEN_OPCODE_VALUE (opc)->base_value)
-#define CGEN_OPCODE_BASE_MASK(opc) CGEN_IFMT_MASK (CGEN_OPCODE_FORMAT (opc))
+  const CGEN_IVALUE ivalue;
+#define CGEN_OPCODE_IVALUE(opc) (& (opc)->ivalue)
+#define CGEN_OPCODE_BASE_MASK_LENGTH(opc) CGEN_IFMT_WORD_LENGTH (CGEN_OPCODE_FORMAT (opc), 0)
+#define CGEN_OPCODE_BASE_MASK(opc) CGEN_IFMT_MASK (CGEN_OPCODE_FORMAT (opc), 0)
+#define CGEN_OPCODE_BASE_VALUE(opc) CGEN_IVALUE_OPCODE (CGEN_OPCODE_IVALUE (opc), 0)
 } CGEN_OPCODE;
 
 /* Instruction attributes.
@@ -1079,9 +1115,13 @@ extern int cgen_macro_insn_count PARAMS 
 /* Return INSN's syntax.  */
 #define CGEN_INSN_SYNTAX(insn) CGEN_OPCODE_SYNTAX (CGEN_INSN_OPCODE (insn))
 
-/* Return size of base mask in bits.  */
-#define CGEN_INSN_MASK_BITSIZE(insn) \
-  CGEN_OPCODE_MASK_BITSIZE (CGEN_INSN_OPCODE (insn))
+/* Return number of "words" in INSN.  */
+#define CGEN_INSN_NUM_WORDS(insn) \
+  CGEN_IFMT_NUM_WORDS (CGEN_OPCODE_FORMAT (CGEN_INSN_OPCODE (insn)))
+
+/* Return the size of the mask of the base part of INSN.  */
+#define CGEN_INSN_BASE_MASK_LENGTH(insn) \
+  CGEN_OPCODE_BASE_MASK_LENGTH (CGEN_INSN_OPCODE (insn))
 
 /* Return mask of base part of INSN.  */
 #define CGEN_INSN_BASE_MASK(insn) \


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]