Implement DMAcnt, DMAret & DMAend with explicit count args.

This commit is contained in:
James Lemke
1998-01-31 00:04:26 +00:00
parent 83f3596372
commit 3b2215c2ed

View File

@ -125,6 +125,8 @@ static subsegT prev_subseg;
static segT prev_seg; static segT prev_seg;
static void s_dmadata PARAMS ((int)); static void s_dmadata PARAMS ((int));
static void s_dmadata_implied PARAMS ((int));
static void s_enddmadata PARAMS ((int));
static void s_dmapackpke PARAMS ((int)); static void s_dmapackpke PARAMS ((int));
static void s_enddirect PARAMS ((int)); static void s_enddirect PARAMS ((int));
static void s_endgpuif PARAMS ((int)); static void s_endgpuif PARAMS ((int));
@ -135,17 +137,17 @@ static void s_state 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, 0 },
{ "dmapackpke", s_dmapackpke, 0 }, { "dmapackpke", s_dmapackpke, 0 },
{ "enddirect", s_enddirect, 0 }, { "enddirect", s_enddirect, 0 },
{ "enddmadata", s_dmadata, 0 }, { "enddmadata", s_enddmadata, 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,.gpuif added to simplify debugging */ /* .vu,.gpuif added to simplify debugging */
{ "vu", s_state, ASM_VU }, { "vu", s_state, ASM_VU },
{ "gpuif", s_state, ASM_GPUIF }, { "gpuif", s_state, ASM_GPUIF },
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };
void void
@ -240,16 +242,63 @@ static void
assemble_dma (str) assemble_dma (str)
char *str; char *str;
{ {
DVP_INSN insn_buf[4]; DVP_INSN insn_buf[4];
const dvp_opcode *opcode; int len; /* Insn's length, in 32 bit words. */
char *f; /* Pointer to allocated frag. */
int i;
const dvp_opcode *opcode;
opcode = assemble_one_insn (DVP_DMA, /*
dma_opcode_lookup_asm (str), dma_operands, Fill the first two words with PKE NOPs.
&str, insn_buf); They may be over-written later if DmaPackPke is on.
if (opcode == NULL) initialize the remainder with zeros.
return; */
if (! output_dma) insn_buf[ 0] = 0;
return; insn_buf[ 1] = 0;
insn_buf[ 2] = 0;
insn_buf[ 3] = 0;
opcode = assemble_one_insn (DVP_DMA,
dma_opcode_lookup_asm (str), dma_operands,
&str, insn_buf);
if( opcode == NULL) return;
if( !output_dma) return;
len = 4;
f = frag_more( len * 4);
/* Write out the PKE / DMA instructions. */
for( i = 0; i < len; ++i)
md_number_to_chars( f + i * 4, insn_buf[i], 4);
/* Create any fixups. */
/* FIXME: It might eventually be possible to combine all the various
copies of this bit of code. */
for( i = 0; i < fixup_count; ++i)
{
int op_type, reloc_type, offset;
const dvp_operand *operand;
#if 0
/*
Create a fixup for this operand.
At this point we do not use a bfd_reloc_code_real_type for
operands residing in the insn, but instead just use the
operand index. This lets us easily handle fixups for any
operand type, although that is admittedly not a very exciting
feature. We pick a BFD reloc type in md_apply_fix.
*/
op_type = fixups[i].opindex;
offset = fixups[i].offset;
reloc_type = encode_fixup_reloc_type (DVP_PKE, op_type);
operand = &pke_operands[op_type];
fix_new_exp (frag_now, f + offset - frag_now->fr_literal, 4,
&fixups[i].exp,
(operand->flags & DVP_OPERAND_RELATIVE_BRANCH) != 0,
(bfd_reloc_code_real_type) reloc_type);
#endif
}
} }
/* Subroutine of md_assemble to assemble PKE instructions. */ /* Subroutine of md_assemble to assemble PKE instructions. */
@ -510,7 +559,7 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
/* Scan the syntax string. If it doesn't match, try the next one. */ /* Scan the syntax string. If it doesn't match, try the next one. */
dvp_opcode_init_parse (); dvp_opcode_init_parse ();
*insn_buf = opcode->value; insn_buf[ opcode->opcode_word] = opcode->value;
fixup_count = 0; fixup_count = 0;
past_opcode_p = 0; past_opcode_p = 0;
num_suffixes = 0; num_suffixes = 0;
@ -641,6 +690,13 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
} }
#endif #endif
if( operand->flags & DVP_OPERAND_DMA_ILD)
{
s_dmadata_implied( 0);
++syn;
break;
}
/* Is there anything left to parse? /* Is there anything left to parse?
We don't check for this at the top because we want to parse We don't check for this at the top because we want to parse
any trailing fake arguments in the syntax string. */ any trailing fake arguments in the syntax string. */
@ -648,35 +704,19 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
if (*str == '\0') if (*str == '\0')
break; break;
#if 0 /* Parse the operand. */
/* Is this the special DMA count operand? */
if( operand->flags & DVP_OPERAND_DMA_COUNT)
dvp_dma_operand_autocount( 0);
if( (operand->flags & DVP_OPERAND_DMA_COUNT) && *str == '*')
{
/* Yes, it is!
Remember that we must compute the length later
when the dma-block label (second operand) is known. */
++str;
dvp_dma_operand_autocount( 1);
}
#endif
if( operand->flags & DVP_OPERAND_DMA_ILD_AUTOCOUNT) if( operand->flags & DVP_OPERAND_DMA_ILD_AUTOCOUNT)
{ {
errmsg = 0; errmsg = 0;
value = parse_dma_ild_autocount( opcode, operand, mods, insn_buf, &str, &errmsg); value = parse_dma_ild_autocount( opcode, operand, mods, insn_buf, &str, &errmsg);
if( errmsg) break; if( errmsg) break;
} }
else if( operand->flags & DVP_OPERAND_DMA_PTR_AUTOCOUNT)
if( operand->flags & DVP_OPERAND_DMA_PTR_AUTOCOUNT)
{ {
errmsg = 0; errmsg = 0;
value = parse_dma_ptr_autocount( opcode, operand, mods, insn_buf, &str, &errmsg); value = parse_dma_ptr_autocount( opcode, operand, mods, insn_buf, &str, &errmsg);
if( errmsg) break; if( errmsg) break;
} }
/* Parse the operand. */
else if (operand->parse) else if (operand->parse)
{ {
errmsg = NULL; errmsg = NULL;
@ -1323,16 +1363,12 @@ insert_operand (cpu, opcode, operand, mods, insn_buf, val, errmsg)
else else
{ {
/* We currently assume a field does not cross a word boundary. */ /* We currently assume a field does not cross a word boundary. */
int shift = ((mods & DVP_MOD_THIS_WORD)
? (operand->shift & 31)
: operand->shift);
DVP_INSN *p = insn_buf + (shift / 32);
if (operand->bits == 32) if (operand->bits == 32)
*p = val; insn_buf[ operand->word] = val;
else else
{ {
shift = shift % 32; long temp = (long) val & ((1 << operand->bits) - 1);
*p |= ((long) val & ((1 << operand->bits) - 1)) << shift; insn_buf[ operand->word] |= temp << operand->shift;
} }
} }
} }
@ -1408,80 +1444,90 @@ insert_operand_final (cpu, operand, mods, insn_buf, val, file, line)
} }
} }
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 static void
s_dmadata( type) s_dmadata_implied( ignore)
int type; int ignore;
{ {
static short state = 0; if( dmadata_state != 0 )
static symbolS *label; /* Points to symbol */
char *name;
const char *prevName;
int temp;
switch( type )
{ {
case 1: /* .DmaData */ as_bad( "DmaData blocks cannot be nested.");
if( state != 0 ) }
{ dmadata_state = 1;
as_bad( "DmaData blocks cannot be nested."); dmadata_name = 0;
ignore_rest_of_line(); }
state = 1;
break;
}
state = 1;
SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */ static void
name = input_line_pointer; s_dmadata( ignore)
int ignore;
{
char *name, c;
if( !is_name_beginner( *name) ) dmadata_name = 0;
{
as_bad( "invalid identifier for \".DmaData\"");
obstack_1grow( &cond_obstack, 0);
ignore_rest_of_line();
break;
}
else
{
char c;
c = get_symbol_end(); if( dmadata_state != 0 )
line_label = label = colon( name); /* user-defined label */ {
*input_line_pointer = c; as_bad( "DmaData blocks cannot be nested.");
ignore_rest_of_line();
return;
}
dmadata_state = 1;
demand_empty_rest_of_line(); SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
} /* if a valid identifyer name */ name = input_line_pointer;
break;
case 0: /* .EndDmaData */ if( !is_name_beginner( *name) )
if( state != 1 ) {
{ as_bad( "invalid identifier for \".DmaData\"");
as_warn( ".EndDmaData encountered outside a DmaData block -- ignored."); obstack_1grow( &cond_obstack, 0); /*FIXME what is this for?*/
ignore_rest_of_line(); ignore_rest_of_line();
state = 0; return;
break; }
}
state = 0;
demand_empty_rest_of_line();
/* c = get_symbol_end();
* "label" points to beginning of block line_label = colon( name); /* user-defined label */
* Create a name for the final label like _$<name> dmadata_name = line_label->bsym->name;
*/ *input_line_pointer = c;
prevName = label->bsym->name;
temp = strlen( prevName) + 1; demand_empty_rest_of_line();
}
static void
s_enddmadata( ignore)
int ignore;
{
if( dmadata_state != 1)
{
as_warn( ".EndDmaData encountered outside a DmaData block -- ignored.");
ignore_rest_of_line();
dmadata_name = 0;
}
dmadata_state = 0;
demand_empty_rest_of_line();
/*
* "label" points to beginning of block
* Create a name for the final label like _$<name>
*/
if( dmadata_name) {
int temp;
char *name;
temp = strlen( dmadata_name) + 1;
name = xmalloc( temp + 2); name = xmalloc( temp + 2);
name[ 0] = '_'; name[ 0] = '_';
name[ 1] = '$'; name[ 1] = '$';
memcpy( name+2, prevName, temp); /* copy original name & \0 */ memcpy( name+2, dmadata_name, temp); /* copy original name & \0 */
colon( name); colon( name);
free( name); free( name);
break;
default:
as_assert( __FILE__, __LINE__, 0);
} }
} }
static void static void
s_dmapackpke( ignore) s_dmapackpke( ignore)
int ignore; int ignore;
@ -1493,10 +1539,10 @@ s_dmapackpke( ignore)
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;
break; break;
case 1: case '1':
dma_pack_pke_p = 1; dma_pack_pke_p = 1;
break; break;
default: default: