(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. (dvp_parse_done): Comment out contents.
(s_enddirect,s_endmpg,s_endunpack): Call demand_empty_rest_of_line. (s_enddirect,s_endmpg,s_endunpack): Call demand_empty_rest_of_line.
(s_state): Handle .vu in included file. (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 end-sanitize-sky
Fri Feb 20 15:03:13 1998 Ian Lance Taylor <ian@cygnus.com> 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 char * unique_name PARAMS ((void));
static long eval_expr PARAMS ((int, int, const char *, ...)); static long eval_expr PARAMS ((int, int, const char *, ...));
static long parse_dma_addr_autocount (); 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 setup_autocount PARAMS ((const char *, DVP_INSN *));
static void insert_operand 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 be provided. (e.g. mpg is followed by vu insns until a .EndMpg is
seen). */ seen). */
typedef enum { 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; } asm_state;
static asm_state cur_asm_state = ASM_INIT; static asm_state cur_asm_state = ASM_INIT;
/* Nonzero if inside .DmaData. */ /* Nonzero if inside .DmaData. */
static int dmadata_state = 0; static int dma_data_state = 0;
/* Label of .DmaData (internally generated for inline data). */ /* 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 /* For variable length instructions, pointer to the initial frag
and pointer into that frag. These only hold valid values if 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_enddmadata PARAMS ((int));
static void s_dmapackvif PARAMS ((int)); static void s_dmapackvif PARAMS ((int));
static void s_enddirect PARAMS ((int)); static void s_enddirect PARAMS ((int));
static void s_endgif PARAMS ((int));
static void s_endmpg PARAMS ((int)); static void s_endmpg PARAMS ((int));
static void s_endunpack PARAMS ((int)); static void s_endunpack PARAMS ((int));
static void s_state PARAMS ((int)); static void s_state PARAMS ((int));
@ -166,6 +174,7 @@ const pseudo_typeS md_pseudo_table[] =
{ "dmapackvif", s_dmapackvif, 0 }, { "dmapackvif", s_dmapackvif, 0 },
{ "enddirect", s_enddirect, 0 }, { "enddirect", s_enddirect, 0 },
{ "enddmadata", s_enddmadata, 0 }, { "enddmadata", s_enddmadata, 0 },
{ "endgif", s_endgif, 0 },
{ "endmpg", s_endmpg, 0 }, { "endmpg", s_endmpg, 0 },
{ "endunpack", s_endunpack, 0 }, { "endunpack", s_endunpack, 0 },
/* .vu added to simplify debugging and creation of input files */ /* .vu added to simplify debugging and creation of input files */
@ -243,6 +252,13 @@ md_assemble (str)
while (isspace (*str)) while (isspace (*str))
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 (cur_asm_state == ASM_INIT)
{ {
if (strncasecmp (str, "dma", 3) == 0) if (strncasecmp (str, "dma", 3) == 0)
@ -446,12 +462,40 @@ assemble_gif (str)
{ {
DVP_INSN insn_buf[4]; DVP_INSN insn_buf[4];
const dvp_opcode *opcode; 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, opcode = assemble_one_insn (DVP_GIF,
gif_opcode_lookup_asm (str), gif_operands, gif_opcode_lookup_asm (str), gif_operands,
&str, insn_buf); &str, insn_buf);
if (opcode == NULL) if (opcode == NULL)
return; 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. */ /* 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) if (operand->flags & DVP_OPERAND_DMA_INLINE)
{ {
inline_dmadata ((mods & DVP_OPERAND_AUTOCOUNT) != 0, inline_dma_data ((mods & DVP_OPERAND_AUTOCOUNT) != 0,
insn_buf); insn_buf);
++syn; ++syn;
continue; continue;
@ -1196,7 +1240,9 @@ scan_symbol (sym)
/* Evaluate an expression. /* Evaluate an expression.
The result is the value of the expression if it can be evaluated, 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) 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 static long
#ifdef USE_STDARG #ifdef USE_STDARG
@ -1229,11 +1275,14 @@ eval_expr (opindex, offset, fmt, va_alist)
if (exp.X_op == O_constant) if (exp.X_op == O_constant)
value = exp.X_add_number; value = exp.X_add_number;
else else
{
if (opindex != 0)
{ {
fixups[fixup_count].exp = exp; fixups[fixup_count].exp = exp;
fixups[fixup_count].opindex = opindex; fixups[fixup_count].opindex = opindex;
fixups[fixup_count].offset = offset; fixups[fixup_count].offset = offset;
++fixup_count; ++fixup_count;
}
value = 0; value = 0;
} }
return value; return value;
@ -1315,25 +1364,25 @@ setup_autocount (name, insn_buf)
/* Record that inline data follows. */ /* Record that inline data follows. */
static void static void
inline_dmadata (autocount_p, insn_buf) inline_dma_data (autocount_p, insn_buf)
int autocount_p; int autocount_p;
DVP_INSN *insn_buf; DVP_INSN *insn_buf;
{ {
if (dmadata_state != 0 ) if (dma_data_state != 0 )
{ {
as_bad ("DmaData blocks cannot be nested."); as_bad ("DmaData blocks cannot be nested.");
return; return;
} }
dmadata_state = 1; dma_data_state = 1;
if (autocount_p) if (autocount_p)
{ {
dmadata_name = S_GET_NAME (create_colon_label ("", unique_name ())); dma_data_name = S_GET_NAME (create_colon_label ("", unique_name ()));
setup_autocount (dmadata_name, insn_buf); setup_autocount (dma_data_name, insn_buf);
} }
else else
dmadata_name = 0; dma_data_name = 0;
} }
/* Compute the auto-count value for a DMA tag with out-of-line data. */ /* Compute the auto-count value for a DMA tag with out-of-line data. */
@ -1514,17 +1563,21 @@ insert_operand (cpu, opcode, operand, mods, insn_buf, val, errmsg)
int shift = ((mods & DVP_MOD_THIS_WORD) int shift = ((mods & DVP_MOD_THIS_WORD)
? (operand->shift & 31) ? (operand->shift & 31)
: operand->shift); : operand->shift);
int word = (mods & DVP_MOD_THIS_WORD) ? 0 : operand->word; /* FIXME: revisit */
#if 0 /* FIXME: revisit */ if (operand->word == 0)
DVP_INSN *p = insn_buf + (shift / 32); {
int word = (mods & DVP_MOD_THIS_WORD) ? 0 : (shift / 32);
if (operand->bits == 32) if (operand->bits == 32)
*p = val; insn_buf[word] = val;
else else
{ {
shift = shift % 32; shift = shift % 32;
*p |= ((long) val & ((1 << operand->bits) - 1)) << shift; insn_buf[word] |= ((long) val & ((1 << operand->bits) - 1)) << shift;
} }
#else }
else
{
int word = (mods & DVP_MOD_THIS_WORD) ? 0 : operand->word;
if (operand->bits == 32) if (operand->bits == 32)
insn_buf[word] = val; insn_buf[word] = val;
else else
@ -1533,7 +1586,7 @@ insert_operand (cpu, opcode, operand, mods, insn_buf, val, errmsg)
insn_buf[word] |= temp << operand->shift; insn_buf[word] |= temp << operand->shift;
} }
} }
#endif }
} }
/* Insert an operand's final value into an instruction. /* Insert an operand's final value into an instruction.
@ -1614,15 +1667,15 @@ s_dmadata (ignore)
{ {
char *name, c; 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."); as_bad ("DmaData blocks cannot be nested.");
ignore_rest_of_line (); ignore_rest_of_line ();
return; return;
} }
dmadata_state = 1; dma_data_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;
@ -1636,7 +1689,7 @@ s_dmadata (ignore)
c = get_symbol_end (); c = get_symbol_end ();
line_label = colon (name); /* user-defined label */ 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; *input_line_pointer = c;
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
@ -1646,23 +1699,23 @@ static void
s_enddmadata (ignore) s_enddmadata (ignore)
int ignore; int ignore;
{ {
if (dmadata_state != 1) if (dma_data_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 ();
dmadata_name = 0; dma_data_name = 0;
} }
dmadata_state = 0; dma_data_state = 0;
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
/* "label" points to beginning of block. /* "label" points to beginning of block.
Create a name for the final label like _$<name>. */ 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. */ /* Fill the data out to a multiple of 16 bytes. */
/* FIXME: Does the fill contents matter? */ /* FIXME: Does the fill contents matter? */
frag_align (4, 0, 0); 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 (); 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 static void
s_endmpg (ignore) s_endmpg (ignore)
int ignore; int ignore;