*** empty log message ***

This commit is contained in:
James Lemke
1998-01-28 02:20:20 +00:00
parent 1f8b7bb9cf
commit 4411d96450
2 changed files with 204 additions and 100 deletions

View File

@ -87,17 +87,17 @@ static void s_vu PARAMS ((int));
/* The target specific pseudo-ops which we support. */ /* The target specific pseudo-ops which we support. */
const pseudo_typeS md_pseudo_table[] = const pseudo_typeS md_pseudo_table[] =
{ {
{ "dmadata", s_dmadata, 1 }, { "dmadata", s_dmadata, 1 },
{ "dmapackpke", s_dmapackpke, 0 }, { "dmapackpke", s_dmapackpke, 0 },
{ "enddirect", s_enddirect, 0 }, { "enddirect", s_enddirect, 0 },
{ "enddmadata", s_dmadata, 0 }, { "enddmadata", s_dmadata, 0 },
{ "endgpuif", s_endgpuif, 0 }, { "endgpuif", s_endgpuif, 0 },
{ "endmpg", s_endmpg, 0 }, { "endmpg", s_endmpg, 0 },
{ "endunpack", s_endunpack, 0 }, { "endunpack", s_endunpack, 0 },
/* .vu,.endvu added to simplify debugging */ /* .vu,.endvu added to simplify debugging */
{ "vu", s_vu, 1 }, { "vu", s_vu, 1 },
{ "endvu", s_vu, 0 }, { "endvu", s_vu, 0 },
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };
void void
@ -541,8 +541,20 @@ assemble_one_insn (cpu, opcode, operand_table, str, insn_buf)
if (*str == '\0') if (*str == '\0')
break; 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. */ /* Parse the operand. */
if (operand->parse) else if (operand->parse)
{ {
errmsg = NULL; errmsg = NULL;
value = (*operand->parse) (opcode, operand, mods, value = (*operand->parse) (opcode, operand, mods,
@ -1019,7 +1031,7 @@ txvu_insert_operand (insn, cpu, operand, mods, val, file, line)
} }
static void static void
s_dmadata( type) s_dmadata( type)
int type; int type;
{ {
static short state = 0; static short state = 0;
@ -1028,9 +1040,10 @@ s_dmadata( type)
const char *prevName; const char *prevName;
int temp; int temp;
switch( type) { switch( type )
case 1: /* .DmaData */ {
if( state != 0) case 1: /* .DmaData */
if( state != 0 )
{ {
as_bad( "DmaData blocks cannot be nested."); as_bad( "DmaData blocks cannot be nested.");
ignore_rest_of_line(); ignore_rest_of_line();
@ -1038,14 +1051,14 @@ s_dmadata( type)
break; break;
} }
state = 1; state = 1;
SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */ SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
name = input_line_pointer; name = input_line_pointer;
if( !is_name_beginner( *name) ) if( !is_name_beginner( *name) )
{ {
as_bad( "invalid identifier for \".DmaData\""); as_bad( "invalid identifier for \".DmaData\"");
obstack_1grow (&cond_obstack, 0); obstack_1grow( &cond_obstack, 0);
ignore_rest_of_line(); ignore_rest_of_line();
break; break;
} }
@ -1054,15 +1067,15 @@ s_dmadata( type)
char c; char c;
c = get_symbol_end(); c = get_symbol_end();
line_label = label = colon( name); /* user-defined label */ line_label = label = colon( name); /* user-defined label */
*input_line_pointer = c; *input_line_pointer = c;
demand_empty_rest_of_line(); demand_empty_rest_of_line();
} /* if a valid identifyer name */ } /* if a valid identifyer name */
break; break;
case 0: /* .EndDmaData */ case 0: /* .EndDmaData */
if( state != 1) if( state != 1 )
{ {
as_warn( ".EndDmaData encountered outside a DmaData block -- ignored."); as_warn( ".EndDmaData encountered outside a DmaData block -- ignored.");
ignore_rest_of_line(); ignore_rest_of_line();
@ -1081,7 +1094,7 @@ s_dmadata( type)
name = malloc( temp + 2); name = malloc( temp + 2);
name[ 0] = '_'; name[ 0] = '_';
name[ 1] = '$'; name[ 1] = '$';
memcpy( name+2, prevName, temp); /* copy original name & \0 */ memcpy( name+2, prevName, temp); /* copy original name & \0 */
colon( name); colon( name);
free( name); free( name);
break; break;
@ -1093,14 +1106,14 @@ s_dmadata( type)
static void static void
s_dmapackpke( ignore) s_dmapackpke( ignore)
int ignore; int ignore;
{ {
/* Syntax: .dmapackpke 0|1 */ /* Syntax: .dmapackpke 0|1 */
struct symbol *label; /* Points to symbol */ struct symbol *label; /* Points to symbol */
char *name; /* points to name of symbol */ char *name; /* points to name of symbol */
SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */ SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
switch( *input_line_pointer++) switch( *input_line_pointer++ )
{ {
case 0: case 0:
dma_pack_pke_p = 0; dma_pack_pke_p = 0;
@ -1146,3 +1159,61 @@ s_vu (enable_p)
{ {
vu_mode_p = 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;
}

View File

@ -1786,24 +1786,29 @@ PRINT_FN (dma_next);
const txvu_operand dma_operands[] = const txvu_operand dma_operands[] =
{ {
/* place holder (??? not sure if needed) */ /* place holder (??? not sure if needed) */
#define DMA_UNUSED 128 #define DMA_UNUSED 128
{ 0 }, { 0 },
/* dma tag flag bits */ /* dma tag flag bits */
#define DMA_FLAGS (DMA_UNUSED + 1) #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 }, parse_dma_flags, insert_dma_flags, extract_dma_flags, print_dma_flags },
/* dma data spec */ /* dma data spec */
#define DMA_DATA (DMA_FLAGS + 1) #define DMA_DATA (DMA_FLAGS + 1)
{ 0, 0, 0, { 0, 0, TXVU_OPERAND_DMA_COUNT,
parse_dma_data, insert_dma_data, extract_dma_data, print_dma_data }, 0, insert_dma_data, extract_dma_data, print_dma_data },
/* dma next tag spec */ /* dma data finalization spec */
#define DMA_NEXT (DMA_DATA + 1) #define DMA_DATA2 (DMA_DATA + 1)
{ 0, 0, 0, { 0, 0, TXVU_OPERAND_FAKE,
parse_dma_next, insert_dma_next, extract_dma_next, print_dma_next }, parse_dma_data2, 0, 0, 0},
/* 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 */ /* end of list place holder */
{ 0 } { 0 }
@ -1811,18 +1816,24 @@ const txvu_operand dma_operands[] =
struct txvu_opcode dma_opcodes[] = struct txvu_opcode dma_opcodes[] =
{ {
/* ??? Some of these may take optional arguments. /* ??? Some of these may take optional arguments.
The way to handle that is to have multiple table entries, those with and The way to handle that is to have multiple table entries, those with and
those without the optional arguments. */ those without the optional arguments. */
{ "dmacnt", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 1 }, /*TODO*/ { "dmacall", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 1},
{ "dmanext", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 2 }, /*TODO*/ { "dmacnt", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 2},
{ "dmaref", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 3 }, { "dmaend", { DMA_FLAGS, SP, DMA_DATA, DMA_DATA2}, 0, 3},
{ "dmarefs", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 4 }, { "dmaend", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 4},
{ "dmacall", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 5 }, /*TODO*/ { "dmanext", { DMA_FLAGS, SP, DMA_DATA, C, DMA_ADDR}, 0, 5},
{ "dmaret", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 6 }, /*TODO { "dmaref", { DMA_FLAGS, SP, DMA_DATA, C, DMA_PTR_ADDR}, 0, 6}, */
{ "dmaend", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 7 } /*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]); 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;
/* DMA parse,insert,extract,print helper fns. */ /* 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 static long
parse_dma_data (opcode, operand, mods, pstr, errmsg) parse_dma_data2( opcode, operand, mods, pstr, errmsg)
const txvu_opcode *opcode; const txvu_opcode *opcode;
const txvu_operand *operand; const txvu_operand *operand;
int mods; int mods;
char **pstr; char **pstr;
const char **errmsg; const char **errmsg;
{ {
char *str = *pstr; /*
long count; If txvu_dma_operand_count() < 0 error
if txvu_dma_operand_count() > 0
if (*str == '*') if dmaref || dmarefs
{ compute from two related symbols
++*pstr; else
/* -1 is a special marker to caller to tell it the count is to be compute from current addr and end symbol
computed from the data. */ store value to count field?
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;
} }
static void static void
@ -1977,28 +1967,50 @@ print_dma_data (opcode, operand, mods, insn, info, value)
} }
static long static long
parse_dma_next (opcode, operand, mods, pstr, errmsg) parse_dma_addr (opcode, operand, mods, pstr, errmsg)
const txvu_opcode *opcode; const txvu_opcode *opcode;
const txvu_operand *operand; const txvu_operand *operand;
int mods; int mods;
char **pstr; char **pstr;
const char **errmsg; const char **errmsg;
{ {
char *start = *pstr; char *start = *pstr;
char *end = scan_symbol (start); char *end = scan_symbol( start);
if (end == start) if( end == start )
{ {
*errmsg = "invalid dma next tag"; *errmsg = "invalid dma next tag";
return 0; return 0;
} }
/* FIXME: unfinished */
*pstr = end; /* FIXME: unfinished
return 0; 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 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_opcode *opcode;
const txvu_operand *operand; const txvu_operand *operand;
int mods; int mods;
@ -2009,7 +2021,7 @@ insert_dma_next (opcode, operand, mods, insn, value, errmsg)
} }
static long static long
extract_dma_next (opcode, operand, mods, insn, pinvalid) extract_dma_addr (opcode, operand, mods, insn, pinvalid)
const txvu_opcode *opcode; const txvu_opcode *opcode;
const txvu_operand *operand; const txvu_operand *operand;
int mods; int mods;
@ -2020,7 +2032,7 @@ extract_dma_next (opcode, operand, mods, insn, pinvalid)
} }
static void 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_opcode *opcode;
const txvu_operand *operand; const txvu_operand *operand;
int mods; int mods;
@ -2435,6 +2447,27 @@ txvu_opcode_init_parse ()
state_vu_mnemonic_bc = -1; state_vu_mnemonic_bc = -1;
state_pke_varlen_p = -1; state_pke_varlen_p = -1;
state_pke_len = -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. */ /* Called by the disassembler before printing an instruction. */