/* 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
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,
}
\f
static void
-s_dmadata( type)
+ s_dmadata( type)
int type;
{
static short state = 0;
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();
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;
}
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();
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;
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;
{
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;
+}
+
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 }
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. */
}
}
-/* 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
}
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;
}
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;
}
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;
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. */