* config/tc-dvp.c (LOCAL_LABEL_PREFIX,END_LABEL_PREFIX): New macros.
authorDoug Evans <dje@google.com>
Thu, 19 Feb 1998 22:51:08 +0000 (22:51 +0000)
committerDoug Evans <dje@google.com>
Thu, 19 Feb 1998 22:51:08 +0000 (22:51 +0000)
(inline_dmadata): Renamed from s_dmadata_implied.
(assemble_one_insn): Rewrite dma operand processing.
(md_apply_fix3): Handle DVP_OPERAND_DMA_NEXT.
(unique_name,setup_autocount): New functions.

gas/ChangeLog
gas/config/tc-dvp.c

index 451455aeb0370fe8fe127daf5c78f6b80e16282b..655840f1008b69b04186f04031f6a965b9432173 100644 (file)
@@ -1,3 +1,25 @@
+start-sanitize-sky
+Thu Feb 19 02:17:03 1998  Doug Evans  <devans@charmed.cygnus.com>
+
+       * config/tc-dvp.c (LOCAL_LABEL_PREFIX,END_LABEL_PREFIX): New macros.
+       (inline_dmadata): Renamed from s_dmadata_implied.
+       (assemble_one_insn): Rewrite dma operand processing.
+       (md_apply_fix3): Handle DVP_OPERAND_DMA_NEXT.
+       (unique_name,setup_autocount): New functions.
+
+       * config/tc-dvp.c: Include stdarg.h/varargs.h.
+       (md_pseudo_table): Add .word.
+       (assemble_dma): Set alignment to 16 bytes.  Enable code that records
+       fixups.
+       (assemble_one_insn): Handle DVP_OPERAND_DMA_{ADDR,AUTOCOUNT}.
+       (md_apply_fix3): Handle DVP_OPERAND_DMA_ADDR.
+       (parse_dma_addr_autocount): Renamed from parse_dma_ptr_autocount.
+       Rewrite.
+       (eval_expr): New function.
+       (create_label,create_colon_label): New function.
+       (s_enddmadata): Rewrite.
+
+end-sanitize-sky
 Wed Feb 18 23:39:46 1998  Richard Henderson  <rth@cygnus.com>
 
        * Makefile.am (install-exec-local): Install properly when ln
index 0d3f19381abd2792146854923c60a48e3e313eb3..07187311d647a9b4b4fd50af5315d1657df58c82 100644 (file)
 /* Compute DMA operand index number of OP.  */
 #define DMA_OPERAND_INDEX(op) ((op) - dma_operands)
 
+/* Our local label prefix.  */
+#define LOCAL_LABEL_PREFIX ".L"
+/* Label prefix for end markers used in autocounts.  */
+#define END_LABEL_PREFIX ".L.end."
+
 static long parse_float PARAMS ((char **, const char **));
 static struct symbol * create_label PARAMS ((const char *, const char *));
 static struct symbol * create_colon_label PARAMS ((const char *, const char *));
+static char * unique_name PARAMS ((void));
 static long eval_expr PARAMS ((int, int, const char *, ...));
-static long parse_dma_ild_autocount ();
 static long parse_dma_addr_autocount ();
+static void inline_dmadata PARAMS ((int, DVP_INSN *));
+static void setup_autocount PARAMS ((const char *, DVP_INSN *));
 
 static void insert_operand 
      PARAMS ((dvp_cpu, const dvp_opcode *, const dvp_operand *, int,
@@ -73,6 +80,11 @@ typedef enum {
 } asm_state;
 static asm_state cur_asm_state = ASM_INIT;
 
+/* Nonzero if inside .DmaData.  */
+static int dmadata_state = 0;
+/* Label of .DmaData (internally generated for inline data).  */
+static const char *dmadata_name;
+
 /* For variable length instructions, pointer to the initial frag
    and pointer into that frag.  These only hold valid values if
    cur_asm_state is one of ASM_MPG, ASM_DIRECT, ASM_UNPACK.  */
@@ -139,7 +151,6 @@ static subsegT prev_subseg;
 static segT prev_seg;
 
 static void s_dmadata PARAMS ((int));
-static void s_dmadata_implied PARAMS ((int));
 static void s_enddmadata PARAMS ((int));
 static void s_dmapackvif PARAMS ((int));
 static void s_enddirect PARAMS ((int));
@@ -565,7 +576,7 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
   start = str = *pstr;
   for ( ; opcode != NULL; opcode = DVP_OPCODE_NEXT_ASM (opcode))
     {
-      int past_opcode_p, num_suffixes, num_operands;
+      int past_opcode_p, num_suffixes;
       const unsigned char *syn;
 
       /* Ensure the mnemonic part matches.  */
@@ -578,11 +589,10 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
       /* Scan the syntax string.  If it doesn't match, try the next one.  */
 
       dvp_opcode_init_parse ();
-      insn_buf[ opcode->opcode_word] = opcode->value;
+      insn_buf[opcode->opcode_word] = opcode->value;
       fixup_count = 0;
       past_opcode_p = 0;
       num_suffixes = 0;
-      num_operands = 0;
 
       /* We don't check for (*str != '\0') here because we want to parse
         any trailing fake arguments in the syntax string.  */
@@ -623,6 +633,15 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
          if (operand->flags & DVP_OPERAND_FAKE)
            {
              long value = 0;
+
+             if (operand->flags & DVP_OPERAND_DMA_INLINE)
+               {
+                 inline_dmadata ((mods & DVP_OPERAND_AUTOCOUNT) != 0,
+                                 insn_buf);
+                 ++syn;
+                 continue;
+               }
+
              if (operand->parse)
                {
                  errmsg = NULL;
@@ -690,23 +709,6 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
              if (operand->flags & DVP_OPERAND_SUFFIX)
                as_fatal ("bad opcode table, suffix wrong");
 
-#if 0 /* commas are in the syntax string now */
-             /* If this is not the first, there must be a comma.  */
-             if (num_operands > 0)
-               {
-                 if (*str != ',')
-                   break;
-                 ++str;
-               }
-#endif
-
-             if (operand->flags & DVP_OPERAND_DMA_ILD)
-               {
-                 s_dmadata_implied (0);
-                 ++syn;
-                 break;
-               }
-
              /* Is there anything left to parse?
                 We don't check for this at the top because we want to parse
                 any trailing fake arguments in the syntax string.  */
@@ -722,16 +724,8 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
                  if (errmsg)
                    break;
                }
-             else if (operand->flags & DVP_OPERAND_DMA_ILD_AUTOCOUNT)
-               {
-                 errmsg = 0;
-                 value = parse_dma_ild_autocount (opcode, operand, mods,
-                                                  insn_buf, &str, &errmsg);
-                 if (errmsg)
-                   break;
-               }
-             else if ((operand->flags & (DVP_OPERAND_DMA_ADDR | DVP_OPERAND_DMA_AUTOCOUNT))
-                      == (DVP_OPERAND_DMA_ADDR | DVP_OPERAND_DMA_AUTOCOUNT))
+             else if ((operand->flags & DVP_OPERAND_DMA_ADDR)
+                      && (mods & DVP_OPERAND_AUTOCOUNT))
                {
                  errmsg = 0;
                  value = parse_dma_addr_autocount (opcode, operand, mods,
@@ -791,7 +785,6 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
                break;
 
              ++syn;
-             ++num_operands;
            }
        }
 
@@ -1017,7 +1010,8 @@ md_apply_fix3 (fixP, valueP, seg)
                  && operand->shift == 0);
          fixP->fx_r_type = BFD_RELOC_MIPS_DVP_11_PCREL;
        }
-      else if ((operand->flags & DVP_OPERAND_DMA_ADDR) != 0)
+      else if ((operand->flags & DVP_OPERAND_DMA_ADDR) != 0
+              || (operand->flags & DVP_OPERAND_DMA_NEXT) != 0)
        {
          assert (operand->bits == 27
                  && operand->shift == 4);
@@ -1166,6 +1160,8 @@ md_atof (type, litP, sizeP)
   return 0;
 }
 \f
+/* Miscellaneous utilities.  */
+
 /* Parse a 32 bit floating point number.
    The result is those 32 bits as an integer.  */
 
@@ -1181,34 +1177,9 @@ parse_float (pstr, errmsg)
   *pstr = p;
   return (words[0] << 16) | words[1];
 }
-\f
-/* Compute the auto-count value for a DMA tag with inline data.  */
-
-static long
-parse_dma_ild_autocount (opcode, operand, mods, insn_buf, pstr, errmsg)
-    const dvp_opcode *opcode;
-    const dvp_operand *operand;
-    int mods;
-    DVP_INSN *insn_buf;
-    char **pstr;
-    const char **errmsg;
-{
-    char *start = *pstr;
-    char *end = start;
-    long retval;
-
-#if 0
-       /* FIXME: unfinished */
-       evaluate the operand as an expression
-       store the value to the count field
-       compute the length as _$EndDma-.
-#endif
 
-    *pstr = end;
-    return 0;
-}
+/* Scan a symbol and return a pointer to one past the end.  */
 
-/* Scan a symbol and return a pointer to one past the end. */
 #define issymchar(ch) (isalnum(ch) || ch == '_')
 static char *
 scan_symbol (sym)
@@ -1219,60 +1190,6 @@ scan_symbol (sym)
   return sym;
 }
 
-/* Compute the auto-count value for a DMA tag with out-of-line data.  */
-
-static long
-parse_dma_addr_autocount (opcode, operand, mods, insn_buf, pstr, errmsg)
-    const dvp_opcode *opcode;
-    const dvp_operand *operand;
-    int mods;
-    DVP_INSN *insn_buf;
-    char **pstr;
-    const char **errmsg;
-{
-  char *start = *pstr;
-  char *end = start;
-  long retval;
-  /* Data reference must be a .DmaData label.  */
-  struct symbol *label, *label2, *endlabel;
-  const char *name;
-  char *name2;
-  int len;
-  long count;
-  char c;
-
-  label = label2 = 0;
-  if (! is_name_beginner (*start))
-    {
-      *errmsg = "invalid .DmaData label";
-      return 0;
-    }
-
-  name = start;
-  end = scan_symbol (name);
-  c = *end;
-  *end = 0;
-  label = symbol_find_or_make (name);
-  *end = c;
-
-  label2 = create_label ("_$", name);
-  /* FIXME: revisit .L. */
-  endlabel = create_label (".L.end.", name);
-
-  retval = eval_expr (dma_operand_addr, operand->word * 4, name);
-  count = eval_expr (dma_operand_count, (operand->word + 1) * 4,
-                    ".L.end.%s - %s", name, name);
-  /* count is in quadwords */
-  count /= 16;
-
-  /* Store the count field. */
-  insn_buf[3] &= 0xffff0000;
-  insn_buf[3] |= count & 0x0000ffff;
-
-  *pstr = end;
-  return retval;
-}
-
 /* Evaluate an expression.
    The result is the value of the expression if it can be evaluated,
    or 0 if it cannot (say because some symbols haven't been defined yet)
@@ -1357,6 +1274,166 @@ create_colon_label (prefix, name)
   free (fullname);
   return result;
 }
+
+/* Return a malloc'd string useful in creating unique labels.  */
+/* ??? Presumably such a routine already exists somewhere
+   [but a first pass at finding it didn't turn up anything].  */
+
+static char *
+unique_name ()
+{
+  static int counter;
+  char *result;
+
+  asprintf (&result, "dvptmp%d", counter);
+  ++counter;
+  return result;
+}
+\f
+/* Compute the auto-count value for a DMA tag.  */
+
+static void
+setup_autocount (name, insn_buf)
+     const char *name;
+     DVP_INSN *insn_buf;
+{
+  long count;
+
+  count = eval_expr (dma_operand_count, 12,
+                    "(%s%s - %s) >> 4", END_LABEL_PREFIX, name, name);
+  /* count is in quadwords */
+  count /= 16;
+
+  /* Store the count field. */
+  insn_buf[3] &= 0xffff0000;
+  insn_buf[3] |= count & 0x0000ffff;
+}
+
+/* Record that inline data follows.  */
+
+static void
+inline_dmadata (autocount_p, insn_buf)
+    int autocount_p;
+    DVP_INSN *insn_buf;
+{
+  if (dmadata_state != 0 )
+    {
+      as_bad ("DmaData blocks cannot be nested.");
+      return;
+    }
+
+  dmadata_state = 1;
+
+  if (autocount_p)
+    {
+      dmadata_name = S_GET_NAME (create_colon_label ("", unique_name ()));
+      setup_autocount (dmadata_name, insn_buf);
+    }
+  else
+    dmadata_name = 0;
+}
+
+/* Compute the auto-count value for a DMA tag with out-of-line data.  */
+
+static long
+parse_dma_addr_autocount (opcode, operand, mods, insn_buf, pstr, errmsg)
+    const dvp_opcode *opcode;
+    const dvp_operand *operand;
+    int mods;
+    DVP_INSN *insn_buf;
+    char **pstr;
+    const char **errmsg;
+{
+  char *start = *pstr;
+  char *end = start;
+  long retval;
+  /* Data reference must be a .DmaData label.  */
+  struct symbol *label, *label2, *endlabel;
+  const char *name;
+  char c;
+
+  label = label2 = 0;
+  if (! is_name_beginner (*start))
+    {
+      *errmsg = "invalid .DmaData label";
+      return 0;
+    }
+
+  name = start;
+  end = scan_symbol (name);
+  c = *end;
+  *end = 0;
+  label = symbol_find_or_make (name);
+  *end = c;
+
+  label2 = create_label ("_$", name);
+  endlabel = create_label (END_LABEL_PREFIX, name);
+
+  retval = eval_expr (dma_operand_addr, 8, name);
+
+  setup_autocount (name, insn_buf);
+
+  *pstr = end;
+  return retval;
+}
+
+/* Parse a DMA data spec which can be either of '*' or a quad word count.  */
+
+static int
+parse_dma_count (pstr, errmsg)
+     char **pstr;
+     const char **errmsg;
+{
+  char *str = *pstr;
+  long count, value;
+  expressionS exp;
+
+  if (*str == '*')
+    {
+      ++*pstr;
+      /* -1 is a special marker to caller to tell it the count is to be
+        computed from the data. */
+      return -1;
+    }
+
+  expression (&exp);
+  if (exp.X_op == O_illegal
+      || exp.X_op == O_absent)
+    ;
+  else if (exp.X_op == O_constant)
+    value = exp.X_add_number;
+  else if (exp.X_op == O_register)
+    as_fatal ("got O_register");
+  else
+    {
+      /* We need to generate a fixup for this expression.  */
+      if (fixup_count >= MAX_FIXUPS )
+       as_fatal ("too many fixups");
+      fixups[fixup_count].exp = exp;
+      fixups[fixup_count].opindex = 0 /*FIXME*/;
+      fixups[fixup_count].offset = 0 /*FIXME*/;
+      ++fixup_count;
+      value = 0;
+    }
+
+  if (isdigit( *str)) /*      ????????needs to accept an expression*/
+    {
+      char *start = str;
+      while (*str && *str != ',')
+       ++str;
+      if (*str != ',')
+       {
+         *errmsg = "invalid dma count";
+         return 0;
+       }
+      count = atoi (start);
+      *pstr = str;
+      return (count);
+    }
+
+  *errmsg = "invalid dma count";
+  return 0;
+}
 \f
 /* Return length in bytes of the variable length VIF insn
    currently being assembled.  */
@@ -1584,23 +1661,7 @@ insert_operand_final (cpu, operand, mods, insn_buf, val, file, line)
   }
 }
 \f
-static short dmadata_state = 0;
-static const char *dmadata_name;
-
-/* Non-zero if .DmaData was implied by a real (non-pseudo) opcode. */
-static int implied_dmadata_p = 0;
-
-static void
-s_dmadata_implied (ignore)
-    int ignore;
-{
-  if (dmadata_state != 0 )
-    {
-      as_bad ("DmaData blocks cannot be nested.");
-    }
-  dmadata_state = 1;
-  dmadata_name = 0;
-}
+/* DVP pseudo ops.  */
 
 static void
 s_dmadata (ignore)
@@ -1656,10 +1717,10 @@ s_enddmadata (ignore)
       /* Fill the data out to a multiple of 16 bytes.  */
       /* FIXME: Does the fill contents matter?  */
       frag_align (4, 0, 0);
-      create_colon_label (".L.end.", dmadata_name);
+      create_colon_label (END_LABEL_PREFIX, dmadata_name);
     }
 }
-\f
+
 static void
 s_dmapackvif (ignore)
     int ignore;
@@ -1784,61 +1845,3 @@ s_endgif (ignore)
      int ignore;
 {
 }
-\f
-/* Parse a DMA data spec which can be either of '*' or a quad word count.  */
-
-static int
-parse_dma_count (pstr, errmsg)
-     char **pstr;
-     const char **errmsg;
-{
-  char *str = *pstr;
-  long count, value;
-  expressionS exp;
-
-  if (*str == '*')
-    {
-      ++*pstr;
-      /* -1 is a special marker to caller to tell it the count is to be
-        computed from the data. */
-      return -1;
-    }
-
-  expression (&exp);
-  if (exp.X_op == O_illegal
-      || exp.X_op == O_absent)
-    ;
-  else if (exp.X_op == O_constant)
-    value = exp.X_add_number;
-  else if (exp.X_op == O_register)
-    as_fatal ("got O_register");
-  else
-    {
-      /* We need to generate a fixup for this expression.  */
-      if (fixup_count >= MAX_FIXUPS )
-       as_fatal ("too many fixups");
-      fixups[fixup_count].exp = exp;
-      fixups[fixup_count].opindex = 0 /*FIXME*/;
-      fixups[fixup_count].offset = 0 /*FIXME*/;
-      ++fixup_count;
-      value = 0;
-    }
-
-  if (isdigit( *str)) /*      ????????needs to accept an expression*/
-    {
-      char *start = str;
-      while (*str && *str != ',')
-       ++str;
-      if (*str != ',')
-       {
-         *errmsg = "invalid dma count";
-         return 0;
-       }
-      count = atoi (start);
-      *pstr = str;
-      return (count);
-    }
-
-  *errmsg = "invalid dma count";
-  return 0;
-}