mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 12:23:31 +08:00
Implement DMAcnt, DMAret & DMAend with explicit count args.
This commit is contained in:
@ -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:
|
||||||
|
Reference in New Issue
Block a user