(asm_state): New state ASM_GIF.

(gif_{insn_type,data_name,insn_frag}): New static locals.
	(md_assemble): Watch for .endgif if in ASM_GIF state.
	(assemble_gif): Complete.
	(s_endgif): Complete.
This commit is contained in:
Doug Evans 1998-02-21 02:12:15 +00:00
parent c2b2e0f0f3
commit 8151801a09
2 changed files with 161 additions and 39 deletions

View file

@ -5,6 +5,11 @@ Fri Feb 20 12:43:02 1998 Doug Evans <devans@canuck.cygnus.com>
(dvp_parse_done): Comment out contents.
(s_enddirect,s_endmpg,s_endunpack): Call demand_empty_rest_of_line.
(s_state): Handle .vu in included file.
(asm_state): New state ASM_GIF.
(gif_{insn_type,data_name,insn_frag}): New static locals.
(md_assemble): Watch for .endgif if in ASM_GIF state.
(assemble_gif): Complete.
(s_endgif): Complete.
end-sanitize-sky
Fri Feb 20 15:03:13 1998 Ian Lance Taylor <ian@cygnus.com>

View file

@ -49,7 +49,7 @@ static struct symbol * create_colon_label PARAMS ((const char *, const char *));
static char * unique_name PARAMS ((void));
static long eval_expr PARAMS ((int, int, const char *, ...));
static long parse_dma_addr_autocount ();
static void inline_dmadata PARAMS ((int, DVP_INSN *));
static void inline_dma_data PARAMS ((int, DVP_INSN *));
static void setup_autocount PARAMS ((const char *, DVP_INSN *));
static void insert_operand
@ -76,14 +76,21 @@ const char FLT_CHARS[] = "dD";
be provided. (e.g. mpg is followed by vu insns until a .EndMpg is
seen). */
typedef enum {
ASM_INIT, ASM_MPG, ASM_DIRECT, ASM_UNPACK, ASM_VU
ASM_INIT, ASM_MPG, ASM_DIRECT, ASM_UNPACK, ASM_VU, ASM_GIF
} asm_state;
static asm_state cur_asm_state = ASM_INIT;
/* Nonzero if inside .DmaData. */
static int dmadata_state = 0;
static int dma_data_state = 0;
/* Label of .DmaData (internally generated for inline data). */
static const char *dmadata_name;
static const char *dma_data_name;
/* Type of gif tag. */
static gif_type gif_insn_type;
/* Name of label of current gif<foo> insn's data. */
static const char *gif_data_name;
/* Pointer to current gif insn in fragment. */
static char *gif_insn_frag;
/* For variable length instructions, pointer to the initial frag
and pointer into that frag. These only hold valid values if
@ -154,6 +161,7 @@ static void s_dmadata PARAMS ((int));
static void s_enddmadata PARAMS ((int));
static void s_dmapackvif PARAMS ((int));
static void s_enddirect PARAMS ((int));
static void s_endgif PARAMS ((int));
static void s_endmpg PARAMS ((int));
static void s_endunpack PARAMS ((int));
static void s_state PARAMS ((int));
@ -166,6 +174,7 @@ const pseudo_typeS md_pseudo_table[] =
{ "dmapackvif", s_dmapackvif, 0 },
{ "enddirect", s_enddirect, 0 },
{ "enddmadata", s_enddmadata, 0 },
{ "endgif", s_endgif, 0 },
{ "endmpg", s_endmpg, 0 },
{ "endunpack", s_endunpack, 0 },
/* .vu added to simplify debugging and creation of input files */
@ -243,6 +252,13 @@ md_assemble (str)
while (isspace (*str))
str++;
/* After a gif tag, no insns can appear until a .endgif is seen. */
if (cur_asm_state == ASM_GIF)
{
as_bad ("missing .endgif");
cur_asm_state = ASM_INIT;
}
if (cur_asm_state == ASM_INIT)
{
if (strncasecmp (str, "dma", 3) == 0)
@ -446,12 +462,40 @@ assemble_gif (str)
{
DVP_INSN insn_buf[4];
const dvp_opcode *opcode;
char *f;
int i;
insn_buf[0] = insn_buf[1] = insn_buf[2] = insn_buf[3] = 0;
opcode = assemble_one_insn (DVP_GIF,
gif_opcode_lookup_asm (str), gif_operands,
&str, insn_buf);
if (opcode == NULL)
return;
/* Do an implicit alignment to a 16 byte boundary. */
frag_align (4, 0, 0);
record_alignment (now_seg, 4);
gif_insn_frag = f = frag_more (16);
for (i = 0; i < 4; ++i)
md_number_to_chars (f + i * 4, insn_buf[i], 4);
/* Insert a label so we can compute the number of quadwords when the
.endgif is seen. */
gif_data_name = S_GET_NAME (create_colon_label ("", unique_name ()));
/* Record the type of the gif tag so we know how to compute nloop
in s_endgif. */
if (strcmp (opcode->mnemonic, "gifpacked") == 0)
gif_insn_type = GIF_PACKED;
else if (strcmp (opcode->mnemonic, "gifreglist") == 0)
gif_insn_type = GIF_REGLIST;
else if (strcmp (opcode->mnemonic, "gifimage") == 0)
gif_insn_type = GIF_IMAGE;
else
abort ();
cur_asm_state = ASM_GIF;
}
/* Subroutine of md_assemble to assemble VU instructions. */
@ -636,7 +680,7 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
if (operand->flags & DVP_OPERAND_DMA_INLINE)
{
inline_dmadata ((mods & DVP_OPERAND_AUTOCOUNT) != 0,
inline_dma_data ((mods & DVP_OPERAND_AUTOCOUNT) != 0,
insn_buf);
++syn;
continue;
@ -1196,7 +1240,9 @@ scan_symbol (sym)
/* Evaluate an expression.
The result is the value of the expression if it can be evaluated,
or 0 if it cannot (say because some symbols haven't been defined yet)
in which case a fixup is queued. */
in which case a fixup is queued.
If OPINDEX is 0, don't queue any fixups, just return 0. */
static long
#ifdef USE_STDARG
@ -1230,10 +1276,13 @@ eval_expr (opindex, offset, fmt, va_alist)
value = exp.X_add_number;
else
{
fixups[fixup_count].exp = exp;
fixups[fixup_count].opindex = opindex;
fixups[fixup_count].offset = offset;
++fixup_count;
if (opindex != 0)
{
fixups[fixup_count].exp = exp;
fixups[fixup_count].opindex = opindex;
fixups[fixup_count].offset = offset;
++fixup_count;
}
value = 0;
}
return value;
@ -1315,25 +1364,25 @@ setup_autocount (name, insn_buf)
/* Record that inline data follows. */
static void
inline_dmadata (autocount_p, insn_buf)
inline_dma_data (autocount_p, insn_buf)
int autocount_p;
DVP_INSN *insn_buf;
{
if (dmadata_state != 0 )
if (dma_data_state != 0 )
{
as_bad ("DmaData blocks cannot be nested.");
return;
}
dmadata_state = 1;
dma_data_state = 1;
if (autocount_p)
{
dmadata_name = S_GET_NAME (create_colon_label ("", unique_name ()));
setup_autocount (dmadata_name, insn_buf);
dma_data_name = S_GET_NAME (create_colon_label ("", unique_name ()));
setup_autocount (dma_data_name, insn_buf);
}
else
dmadata_name = 0;
dma_data_name = 0;
}
/* Compute the auto-count value for a DMA tag with out-of-line data. */
@ -1514,26 +1563,30 @@ insert_operand (cpu, opcode, operand, mods, insn_buf, val, errmsg)
int shift = ((mods & DVP_MOD_THIS_WORD)
? (operand->shift & 31)
: operand->shift);
int word = (mods & DVP_MOD_THIS_WORD) ? 0 : operand->word;
#if 0 /* FIXME: revisit */
DVP_INSN *p = insn_buf + (shift / 32);
if (operand->bits == 32)
*p = val;
else
/* FIXME: revisit */
if (operand->word == 0)
{
shift = shift % 32;
*p |= ((long) val & ((1 << operand->bits) - 1)) << shift;
int word = (mods & DVP_MOD_THIS_WORD) ? 0 : (shift / 32);
if (operand->bits == 32)
insn_buf[word] = val;
else
{
shift = shift % 32;
insn_buf[word] |= ((long) val & ((1 << operand->bits) - 1)) << shift;
}
}
#else
if (operand->bits == 32)
insn_buf[word] = val;
else
{
long temp = (long) val & ((1 << operand->bits) - 1);
insn_buf[word] |= temp << operand->shift;
int word = (mods & DVP_MOD_THIS_WORD) ? 0 : operand->word;
if (operand->bits == 32)
insn_buf[word] = val;
else
{
long temp = (long) val & ((1 << operand->bits) - 1);
insn_buf[word] |= temp << operand->shift;
}
}
}
#endif
}
/* Insert an operand's final value into an instruction.
@ -1614,15 +1667,15 @@ s_dmadata (ignore)
{
char *name, c;
dmadata_name = 0;
dma_data_name = 0;
if (dmadata_state != 0)
if (dma_data_state != 0)
{
as_bad ("DmaData blocks cannot be nested.");
ignore_rest_of_line ();
return;
}
dmadata_state = 1;
dma_data_state = 1;
SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */
name = input_line_pointer;
@ -1636,7 +1689,7 @@ s_dmadata (ignore)
c = get_symbol_end ();
line_label = colon (name); /* user-defined label */
dmadata_name = S_GET_NAME (line_label);
dma_data_name = S_GET_NAME (line_label);
*input_line_pointer = c;
demand_empty_rest_of_line ();
@ -1646,23 +1699,23 @@ static void
s_enddmadata (ignore)
int ignore;
{
if (dmadata_state != 1)
if (dma_data_state != 1)
{
as_warn (".EndDmaData encountered outside a DmaData block -- ignored.");
ignore_rest_of_line ();
dmadata_name = 0;
dma_data_name = 0;
}
dmadata_state = 0;
dma_data_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)
if (dma_data_name)
{
/* Fill the data out to a multiple of 16 bytes. */
/* FIXME: Does the fill contents matter? */
frag_align (4, 0, 0);
create_colon_label (END_LABEL_PREFIX, dmadata_name);
create_colon_label (END_LABEL_PREFIX, dma_data_name);
}
}
@ -1719,6 +1772,70 @@ s_enddirect (ignore)
demand_empty_rest_of_line ();
}
static void
s_endgif (ignore)
int ignore;
{
long count;
int nloop = gif_nloop ();
if (cur_asm_state != ASM_GIF)
{
as_bad (".endgif doesn't follow a gif tag");
return;
}
cur_asm_state = ASM_INIT;
if (gif_insn_type == GIF_PACKED)
count = eval_expr (0, 0, "(. - %s) >> 4", gif_data_name);
else
count = eval_expr (0, 0, "(. - %s) >> 3", gif_data_name);
if (count < 0
|| fixup_count != 0)
{
as_bad ("bad data count");
return;
}
/* Validate nloop if specified. Otherwise write the computed value into
the insn. */
if (nloop != -1)
{
int ok_p;
switch (gif_insn_type)
{
case GIF_PACKED :
case GIF_REGLIST :
ok_p = count == nloop * gif_nregs ();
break;
case GIF_IMAGE :
ok_p = count == nloop;
break;
}
if (! ok_p)
{
as_bad ("nloop value does not match size of data");
return;
}
}
else
{
DVP_INSN insn = bfd_getl32 (gif_insn_frag + 12);
char *file;
unsigned int line;
as_where (&file, &line);
insert_operand_final (DVP_GIF, &gif_operands[gif_operand_nloop],
DVP_MOD_THIS_WORD, &insn,
(offsetT) nloop, file, line);
bfd_putl32 ((bfd_vma) insn, gif_insn_frag + 12);
}
gif_data_name = NULL;
demand_empty_rest_of_line ();
}
static void
s_endmpg (ignore)
int ignore;