*** empty log message ***
authorJames Lemke <jlemke@cygnus>
Wed, 28 Jan 1998 02:20:20 +0000 (02:20 +0000)
committerJames Lemke <jlemke@cygnus>
Wed, 28 Jan 1998 02:20:20 +0000 (02:20 +0000)
gas/config/tc-txvu.c
opcodes/txvu-opc.c

index a0cb11da8494c21dfa3f4e65e20f8fd2b02fe70f..a6b18dedded38597ff0f09289d8985a892282f43 100644 (file)
@@ -87,17 +87,17 @@ static void s_vu PARAMS ((int));
 /* The target specific pseudo-ops which we support.  */
 const pseudo_typeS md_pseudo_table[] =
 {
-  { "dmadata", s_dmadata, 1 },
-  { "dmapackpke", s_dmapackpke, 0 },
-  { "enddirect", s_enddirect, 0 },
-  { "enddmadata", s_dmadata, 0 },
-  { "endgpuif", s_endgpuif, 0 },
-  { "endmpg", s_endmpg, 0 },
-  { "endunpack", s_endunpack, 0 },
-  /* .vu,.endvu added to simplify debugging */
-  { "vu", s_vu, 1 },
-  { "endvu", s_vu, 0 },
-  { NULL, NULL, 0 }
+    { "dmadata", s_dmadata, 1 },
+    { "dmapackpke", s_dmapackpke, 0 },
+    { "enddirect", s_enddirect, 0 },
+    { "enddmadata", s_dmadata, 0 },
+    { "endgpuif", s_endgpuif, 0 },
+    { "endmpg", s_endmpg, 0 },
+    { "endunpack", s_endunpack, 0 },
+    /* .vu,.endvu added to simplify debugging */
+    { "vu", s_vu, 1 },
+    { "endvu", s_vu, 0 },
+    { NULL, NULL, 0 }
 };
 \f
 void
@@ -541,8 +541,20 @@ assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
              if (*str == '\0')
                break;
 
+             /* Is this the special DMA count operand? */
+             if( operand->flags & TXVU_OPERAND_DMA_COUNT)
+                 txvu_dma_operand_count( 0);
+             if( (operand->flags & TXVU_OPERAND_DMA_COUNT) && *str == '*')
+             {
+                 /* Yes, it is!
+                 Remember that we must compute the length later
+                 when the dma-block label (second operand) is known. */
+                 ++*pstr;
+                 txvu_dma_operand_count( 1);
+             }
+
              /* Parse the operand.  */
-             if (operand->parse)
+             else if (operand->parse)
                {
                  errmsg = NULL;
                  value = (*operand->parse) (opcode, operand, mods,
@@ -1019,7 +1031,7 @@ txvu_insert_operand (insn, cpu, operand, mods, val, file, line)
 }
 \f
 static void
-s_dmadata( type)
+  s_dmadata( type)
     int type;
 {
     static short state = 0;
@@ -1028,9 +1040,10 @@ s_dmadata( type)
     const char *prevName;
     int temp;
 
-    switch( type) {
-    case 1:    /* .DmaData */
-       if( state != 0)
+    switch( type )
+    {
+    case 1:                            /* .DmaData */
+       if( state != 0 )
        {
            as_bad( "DmaData blocks cannot be nested.");
            ignore_rest_of_line();
@@ -1038,14 +1051,14 @@ s_dmadata( type)
            break;
        }
        state = 1;
-         
+
        SKIP_WHITESPACE();              /* Leading whitespace is part of operand. */
        name = input_line_pointer;
-      
+
        if( !is_name_beginner( *name) )
        {
            as_bad( "invalid identifier for \".DmaData\"");
-           obstack_1grow (&cond_obstack, 0);
+           obstack_1grow&cond_obstack, 0);
            ignore_rest_of_line();
            break;
        }
@@ -1054,15 +1067,15 @@ s_dmadata( type)
            char c;
 
            c = get_symbol_end();
-           line_label = label = colon( name);  /* user-defined label */
+           line_label = label = colon( name);    /* user-defined label */
            *input_line_pointer = c;
 
            demand_empty_rest_of_line();
        }                               /* if a valid identifyer name */
        break;
 
-    case 0:    /* .EndDmaData */
-       if( state != 1)
+    case 0:                            /* .EndDmaData */
+       if( state != 1 )
        {
            as_warn( ".EndDmaData encountered outside a DmaData block -- ignored.");
            ignore_rest_of_line();
@@ -1081,7 +1094,7 @@ s_dmadata( type)
        name = malloc( temp + 2);
        name[ 0] = '_';
        name[ 1] = '$';
-       memcpy( name+2, prevName, temp);        /* copy original name & \0 */
+       memcpy( name+2, prevName, temp);    /* copy original name & \0 */
        colon( name);
        free( name);
        break;
@@ -1093,14 +1106,14 @@ s_dmadata( type)
 
 static void
 s_dmapackpke( ignore)
-     int ignore;
+    int ignore;
 {
     /* Syntax: .dmapackpke 0|1 */
     struct symbol *label;              /* Points to symbol */
     char *name;                                /* points to name of symbol */
 
-    SKIP_WHITESPACE();         /* Leading whitespace is part of operand. */
-    switch( *input_line_pointer++)
+    SKIP_WHITESPACE();                 /* Leading whitespace is part of operand. */
+    switch( *input_line_pointer++ )
     {
     case 0:
        dma_pack_pke_p = 0;
@@ -1146,3 +1159,61 @@ s_vu (enable_p)
 {
   vu_mode_p = enable_p;
 }
+
+/* Parse a DMA data spec which can be either of '*' or a quad word count.  */
+
+static void
+parse_dma_count( pstr, errmsg)
+    char **pstr;
+    const char **errmsg;
+{
+    char *str = *pstr;
+    long count;
+
+    if( *str == '*' )
+    {
+       ++*pstr;
+       /* -1 is a special marker to caller to tell it the count is to be
+       computed from the data. */
+       return -1;
+    }
+
+    expressionS exp;
+    expression( &exp);
+    if( exp.X_op == O_illegal
+       || exp.X_op == O_absent )
+       break;
+    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 = index;
+       ++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;
+}
+
index 8db0ad80059b2370036e45fb24509f724b2c1a60..1d4d0f7fc8bd95dd16f71a3b93d164677b9084b9 100644 (file)
@@ -1786,24 +1786,29 @@ PRINT_FN (dma_next);
 
 const txvu_operand dma_operands[] =
 {
-  /* place holder (??? not sure if needed) */
+    /* place holder (??? not sure if needed) */
 #define DMA_UNUSED 128
-  { 0 },
+    { 0 },
 
-  /* dma tag flag bits */
+    /* dma tag flag bits */
 #define DMA_FLAGS (DMA_UNUSED + 1)
-  { 0, 0, TXVU_OPERAND_SUFFIX,
+    { 0, 0, TXVU_OPERAND_SUFFIX,
       parse_dma_flags, insert_dma_flags, extract_dma_flags, print_dma_flags },
 
-  /* dma data spec */
+    /* dma data spec */
 #define DMA_DATA (DMA_FLAGS + 1)
-  { 0, 0, 0,
-      parse_dma_data, insert_dma_data, extract_dma_data, print_dma_data },
+    { 0, 0, TXVU_OPERAND_DMA_COUNT,
+      0, insert_dma_data, extract_dma_data, print_dma_data },
+
+    /* dma data finalization spec */
+#define DMA_DATA2 (DMA_DATA + 1)
+    { 0, 0, TXVU_OPERAND_FAKE,
+      parse_dma_data2, 0, 0, 0},
 
-  /* dma next tag spec */
-#define DMA_NEXT (DMA_DATA + 1)
-  { 0, 0, 0,
-      parse_dma_next, insert_dma_next, extract_dma_next, print_dma_next },
+    /* dma next tag spec */
+#define DMA_ADDR (DMA_DATA2 + 1)
+    { 0, 0, 0,
+      parse_dma_addr, insert_dma_addr, extract_dma_addr, print_dma_addr},
 
 /* end of list place holder */
   { 0 }
@@ -1811,18 +1816,24 @@ const txvu_operand dma_operands[] =
 
 struct txvu_opcode dma_opcodes[] =
 {
-  /* ??? Some of these may take optional arguments.
-     The way to handle that is to have multiple table entries, those with and
-     those without the optional arguments.  */
-  { "dmacnt", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 1 },
-  { "dmanext", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 2 },
-  { "dmaref", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 3 },
-  { "dmarefs", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 4 },
-  { "dmacall", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 5 },
-  { "dmaret", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 6 },
-  { "dmaend", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 7 }
+    /* ??? Some of these may take optional arguments.
+    The way to handle that is to have multiple table entries, those with and
+    those without the optional arguments.  */
+/*TODO*/    { "dmacall", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 1},
+/*TODO*/    { "dmacnt", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 2},
+    { "dmaend", { DMA_FLAGS, SP, DMA_DATA, DMA_DATA2}, 0, 3},
+    { "dmaend", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 4},
+/*TODO*/    { "dmanext", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 5},
+/*TODO      { "dmaref", { DMA_FLAGS, SP, DMA_DATA, C, DMA_PTR_ADDR}, 0, 6},    */
+/*TODO      { "dmarefs", { DMA_FLAGS, SP, DMA_DATA, C, DMA_PTR_ADDR}, 0, 7},   */
+/*TODO*/    { "dmaret", { DMA_FLAGS, SP, DMA_DATA, DMA_DATA2}, 0, 8}
+/*TODO*/    { "dmaret", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 9}
 };
 const int dma_opcodes_count = sizeof (dma_opcodes) / sizeof (dma_opcodes[0]);
+
+/* Did the current DMA instruction has specify "*" as its length operand?
+-1=uninitialized, 0=no, 1=yes. */
+static int state_dma_operand_count_p;
 \f
 /* DMA parse,insert,extract,print helper fns.  */
 
@@ -1902,44 +1913,23 @@ print_dma_flags (opcode, operand, mods, insn, info, value)
     }
 }
 
-/* Parse a DMA data spec which can be either of '*' or a quad word count.  */
-
 static long
-parse_dma_data (opcode, operand, mods, pstr, errmsg)
-     const txvu_opcode *opcode;
-     const txvu_operand *operand;
-     int mods;
-     char **pstr;
-     const char **errmsg;
-{
-  char *str = *pstr;
-  long count;
-
-  if (*str == '*')
-    {
-      ++*pstr;
-      /* -1 is a special marker to caller to tell it the count is to be
-        computed from the data.  */
-      return -1;
-    }
-
-  if (isdigit (*str))
-    {
-      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;
+parse_dma_data2( opcode, operand, mods, pstr, errmsg)
+    const txvu_opcode *opcode;
+    const txvu_operand *operand;
+    int mods;
+    char **pstr;
+    const char **errmsg;
+{
+    /*
+    If txvu_dma_operand_count() < 0 error
+    if txvu_dma_operand_count() > 0
+       if dmaref || dmarefs
+           compute from two related symbols
+       else
+           compute from current addr and end symbol
+       store value to count field?
+    */
 }
 
 static void
@@ -1977,28 +1967,50 @@ print_dma_data (opcode, operand, mods, insn, info, value)
 }
 
 static long
-parse_dma_next (opcode, operand, mods, pstr, errmsg)
-     const txvu_opcode *opcode;
-     const txvu_operand *operand;
-     int mods;
-     char **pstr;
-     const char **errmsg;
+parse_dma_addr (opcode, operand, mods, pstr, errmsg)
+    const txvu_opcode *opcode;
+    const txvu_operand *operand;
+    int mods;
+    char **pstr;
+    const char **errmsg;
 {
-  char *start = *pstr;
-  char *end = scan_symbol (start);
+    char *start = *pstr;
+    char *end = scan_symbol( start);
 
-  if (end == start)
+    if( end == start )
     {
-      *errmsg = "invalid dma next tag";
-      return 0;
+       *errmsg = "invalid dma next tag";
+       return 0;
     }
-  /* FIXME: unfinished */
-  *pstr = end;
-  return 0;
+
+    /* FIXME: unfinished
+    if txvu_dma_operand_count() > 0
+       if dmaref || dmarefs
+           this operand must be a symbol (vs an expression)
+           lookup the symbol
+           store the symbol's value in the addr field (relocs?)
+           compute the end_symbol's name
+           lookup the end_symbol
+           if not found: error
+           compute the length as _$<name>-<name>
+       else
+           evaluate the operand as an expression
+           store the value to the count field
+           compute the length as _$EndDma-.
+       store the count field
+    else
+       evaluate the operand as an expression
+       store the value to the count field
+    */
+
+    parse_dma_data2( opcode, operand, mods, pstr, errmsg);
+
+    *pstr = end;
+    return 0;
 }
 
 static void
-insert_dma_next (opcode, operand, mods, insn, value, errmsg)
+insert_dma_addr (opcode, operand, mods, insn, value, errmsg)
      const txvu_opcode *opcode;
      const txvu_operand *operand;
      int mods;
@@ -2009,7 +2021,7 @@ insert_dma_next (opcode, operand, mods, insn, value, errmsg)
 }
 
 static long
-extract_dma_next (opcode, operand, mods, insn, pinvalid)
+extract_dma_addr (opcode, operand, mods, insn, pinvalid)
      const txvu_opcode *opcode;
      const txvu_operand *operand;
      int mods;
@@ -2020,7 +2032,7 @@ extract_dma_next (opcode, operand, mods, insn, pinvalid)
 }
 
 static void
-print_dma_next (opcode, operand, mods, insn, info, value)
+print_dma_addr (opcode, operand, mods, insn, info, value)
      const txvu_opcode *opcode;
      const txvu_operand *operand;
      int mods;
@@ -2435,6 +2447,27 @@ txvu_opcode_init_parse ()
   state_vu_mnemonic_bc = -1;
   state_pke_varlen_p = -1;
   state_pke_len = -1;
+  state_dma_operand_count_p = -1;
+}
+
+/*
+Query or set the current type of a DMA length operand, explicit or computed by "as".
+The return value is the setting before "action" is applied:
+    -1=uninitialized, 0=explicit, +1=computed
+The value of "action" is interpreted as:
+    -1=no change, 0=set explicit, +1=set computed
+*/
+int
+txvu_dma_operand_count( action)
+{
+    int result = state_dma_operand_count;
+
+    if( action == 0)
+       state_dma_operand_count = 0;
+    else if( action > 0)
+        state_dma_operand_count_p = 1;
+
+    return result;
 }
 
 /* Called by the disassembler before printing an instruction.  */