(asm_state_stack): Maintain stack of parsing states.

({push,pop,set}_asm_state): New functions.
	(CUR_ASM_STATE): Renamed from cur_asm_state, all uses updated.
This commit is contained in:
Doug Evans 1998-02-21 03:26:47 +00:00
parent 8151801a09
commit 498fcb9cdb
2 changed files with 169 additions and 92 deletions

View file

@ -1,11 +1,14 @@
start-sanitize-sky
Fri Feb 20 12:43:02 1998 Doug Evans <devans@canuck.cygnus.com>
* confirg/tc-dvp.c (md_assemble): Handle ASM_DIRECT state.
* config/tc-dvp.c (md_assemble): Handle ASM_DIRECT state.
(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.
(asm_state_stack): Maintain stack of parsing states.
({push,pop,set}_asm_state): New functions.
(CUR_ASM_STATE): Renamed from cur_asm_state, all uses updated.
(gif_{insn_type,data_name,insn_frag}): New static locals.
(md_assemble): Watch for .endgif if in ASM_GIF state.
(assemble_gif): Complete.

View file

@ -74,11 +74,32 @@ const char FLT_CHARS[] = "dD";
Instructions like mpg and direct are followed by a restricted set of
instructions. In the case of a '*' length argument an end marker must
be provided. (e.g. mpg is followed by vu insns until a .EndMpg is
seen). */
seen).
Allowed state transitions:
ASM_INIT -> ASM_MPG
ASM_DIRECT -> ASM_GIF
ASM_UNPACK
ASM_VU
*/
typedef enum {
ASM_INIT, ASM_MPG, ASM_DIRECT, ASM_UNPACK, ASM_VU, ASM_GIF
ASM_INIT, ASM_DIRECT, ASM_MPG, ASM_UNPACK, ASM_VU, ASM_GIF
} asm_state;
static asm_state cur_asm_state = ASM_INIT;
/* We need to maintain a stack of the current and previous status to handle
such things as "direct ...; gifpacked ... ; .endgif ; .enddirect". */
#define MAX_STATE_DEPTH 2
static asm_state asm_state_stack[MAX_STATE_DEPTH];
/* Current state's index in the stack. */
static int cur_state_index;
/* Macro to fetch the current state. */
#define CUR_ASM_STATE (asm_state_stack[cur_state_index])
/* Functions to push/pop the state stack. */
static void push_asm_state PARAMS ((asm_state));
static void pop_asm_state PARAMS ((int));
static void set_asm_state PARAMS ((asm_state));
/* Nonzero if inside .DmaData. */
static int dma_data_state = 0;
@ -94,7 +115,7 @@ 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
cur_asm_state is one of ASM_MPG, ASM_DIRECT, ASM_UNPACK. */
CUR_ASM_STATE is one of ASM_MPG, ASM_DIRECT, ASM_UNPACK. */
static fragS *cur_varlen_frag;
static char *cur_varlen_insn;
/* The length value specified in the insn, or -1 if '*'. */
@ -161,9 +182,9 @@ 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_endgif PARAMS ((int));
static void s_state PARAMS ((int));
/* The target specific pseudo-ops which we support. */
@ -174,9 +195,9 @@ 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 },
{ "endgif", s_endgif, 0 },
/* .vu added to simplify debugging and creation of input files */
{ "vu", s_state, ASM_VU },
{ NULL, NULL, 0 }
@ -200,7 +221,8 @@ md_begin ()
This involves computing the hash chains. */
dvp_opcode_init_tables (0);
cur_asm_state = ASM_INIT;
cur_state_index = 0;
set_asm_state (ASM_INIT);
dma_pack_vif_p = 0;
}
@ -253,13 +275,27 @@ md_assemble (str)
str++;
/* After a gif tag, no insns can appear until a .endgif is seen. */
if (cur_asm_state == ASM_GIF)
if (CUR_ASM_STATE == ASM_GIF)
{
as_bad ("missing .endgif");
cur_asm_state = ASM_INIT;
pop_asm_state (1);
}
/* Ditto for unpack. */
if (CUR_ASM_STATE == ASM_UNPACK)
{
as_bad ("missing .endunpack");
pop_asm_state (1);
}
#if 0 /* this doesn't work of course as gif insns may follow */
/* Ditto for direct. */
if (CUR_ASM_STATE == ASM_DIRECT)
{
as_bad ("missing .enddirect");
pop_asm_state (1);
}
#endif
if (cur_asm_state == ASM_INIT)
if (CUR_ASM_STATE == ASM_INIT)
{
if (strncasecmp (str, "dma", 3) == 0)
assemble_dma (str);
@ -268,10 +304,10 @@ md_assemble (str)
else
assemble_vif (str);
}
else if (cur_asm_state == ASM_DIRECT)
else if (CUR_ASM_STATE == ASM_DIRECT)
assemble_gif (str);
else if (cur_asm_state == ASM_VU
|| cur_asm_state == ASM_MPG)
else if (CUR_ASM_STATE == ASM_VU
|| CUR_ASM_STATE == ASM_MPG)
assemble_vu (str);
else
as_fatal ("unknown parse state");
@ -445,11 +481,11 @@ assemble_vif (str)
cur_varlen_insn = f;
cur_varlen_value = data_len;
if (opcode->flags & VIF_OPCODE_MPG)
cur_asm_state = ASM_MPG;
set_asm_state (ASM_MPG);
else if (opcode->flags & VIF_OPCODE_DIRECT)
cur_asm_state = ASM_DIRECT;
set_asm_state (ASM_DIRECT);
else if (opcode->flags & VIF_OPCODE_UNPACK)
cur_asm_state = ASM_UNPACK;
set_asm_state (ASM_UNPACK);
}
}
}
@ -495,7 +531,7 @@ assemble_gif (str)
gif_insn_type = GIF_IMAGE;
else
abort ();
cur_asm_state = ASM_GIF;
push_asm_state (ASM_GIF);
}
/* Subroutine of md_assemble to assemble VU instructions. */
@ -864,7 +900,45 @@ assemble_one_insn (cpu, opcode, operand_table, pstr, insn_buf)
as_bad ("bad instruction `%s'", start);
return 0;
}
/* Push/pop the current parsing state. */
static void
push_asm_state (new_state)
asm_state new_state;
{
++cur_state_index;
if (cur_state_index == MAX_STATE_DEPTH)
as_fatal ("unexpected state push");
asm_state_stack[cur_state_index] = new_state;
}
/* TOP_OK_P is non-zero if it's ok that we're at the top of the stack.
This happens if there are errors in the assembler code.
We just reset the stack to its "init" state. */
static void
pop_asm_state (top_ok_p)
int top_ok_p;
{
if (cur_state_index == 0)
{
if (top_ok_p)
asm_state_stack[cur_state_index] = ASM_INIT;
else
as_fatal ("unexpected state pop");
}
else
--cur_state_index;
}
static void
set_asm_state (state)
asm_state state;
{
CUR_ASM_STATE = state;
}
void
md_operand (expressionP)
expressionS *expressionP;
@ -895,11 +969,11 @@ dvp_parse_done ()
#if 0 /* ??? Doesn't work unless we keep track of the nested include file
level. */
/* Check for missing .EndMpg, and supply one if necessary. */
if (cur_asm_state == ASM_MPG)
if (CUR_ASM_STATE == ASM_MPG)
s_endmpg (0);
else if (cur_asm_state == ASM_DIRECT)
else if (CUR_ASM_STATE == ASM_DIRECT)
s_enddirect (0);
else if (cur_asm_state == ASM_UNPACK)
else if (CUR_ASM_STATE == ASM_UNPACK)
s_endunpack (0);
#endif
}
@ -1749,7 +1823,7 @@ s_enddirect (ignore)
{
int byte_len;
if (cur_asm_state != ASM_DIRECT)
if (CUR_ASM_STATE != ASM_DIRECT)
{
as_bad ("`.enddirect' has no matching `direct' instruction");
return;
@ -1762,7 +1836,7 @@ s_enddirect (ignore)
if (output_vif)
install_vif_length (cur_varlen_insn, byte_len);
cur_asm_state = ASM_INIT;
set_asm_state (ASM_INIT);
/* These needn't be reset, but to catch bugs they are. */
cur_varlen_frag = NULL;
@ -1772,6 +1846,71 @@ s_enddirect (ignore)
demand_empty_rest_of_line ();
}
static void
s_endmpg (ignore)
int ignore;
{
int byte_len;
if (CUR_ASM_STATE != ASM_MPG)
{
as_bad ("`.endmpg' has no matching `mpg' instruction");
return;
}
byte_len = cur_vif_insn_length ();
if (cur_varlen_value != -1
&& cur_varlen_value * 8 != byte_len)
as_warn ("length in `mpg' instruction does not match length of data");
if (output_vif)
install_vif_length (cur_varlen_insn, byte_len);
set_asm_state (ASM_INIT);
/* These needn't be reset, but to catch bugs they are. */
cur_varlen_frag = NULL;
cur_varlen_insn = NULL;
cur_varlen_value = 0;
/* Update $.MpgLoc. */
vif_set_mpgloc (vif_get_mpgloc () + byte_len);
demand_empty_rest_of_line ();
}
static void
s_endunpack (ignore)
int ignore;
{
int byte_len;
if (CUR_ASM_STATE != ASM_UNPACK)
{
as_bad ("`.endunpack' has no matching `unpack' instruction");
return;
}
byte_len = cur_vif_insn_length ();
#if 0 /* unpack doesn't support prespecifying a length */
if (cur_varlen_value * 16 != bytelen)
as_warn ("length in `direct' instruction does not match length of data");
#endif
if (output_vif)
install_vif_length (cur_varlen_insn, byte_len);
set_asm_state (ASM_INIT);
/* These needn't be reset, but to catch bugs they are. */
cur_varlen_frag = NULL;
cur_varlen_insn = NULL;
cur_varlen_value = 0;
/* Update $.UnpackLoc. */
vif_set_unpackloc (vif_get_unpackloc () + byte_len);
demand_empty_rest_of_line ();
}
static void
s_endgif (ignore)
int ignore;
@ -1779,12 +1918,12 @@ s_endgif (ignore)
long count;
int nloop = gif_nloop ();
if (cur_asm_state != ASM_GIF)
if (CUR_ASM_STATE != ASM_GIF)
{
as_bad (".endgif doesn't follow a gif tag");
return;
}
cur_asm_state = ASM_INIT;
pop_asm_state (0);
if (gif_insn_type == GIF_PACKED)
count = eval_expr (0, 0, "(. - %s) >> 4", gif_data_name);
@ -1836,71 +1975,6 @@ s_endgif (ignore)
demand_empty_rest_of_line ();
}
static void
s_endmpg (ignore)
int ignore;
{
int byte_len;
if (cur_asm_state != ASM_MPG)
{
as_bad ("`.endmpg' has no matching `mpg' instruction");
return;
}
byte_len = cur_vif_insn_length ();
if (cur_varlen_value != -1
&& cur_varlen_value * 8 != byte_len)
as_warn ("length in `mpg' instruction does not match length of data");
if (output_vif)
install_vif_length (cur_varlen_insn, byte_len);
cur_asm_state = ASM_INIT;
/* These needn't be reset, but to catch bugs they are. */
cur_varlen_frag = NULL;
cur_varlen_insn = NULL;
cur_varlen_value = 0;
/* Update $.MpgLoc. */
vif_set_mpgloc (vif_get_mpgloc () + byte_len);
demand_empty_rest_of_line ();
}
static void
s_endunpack (ignore)
int ignore;
{
int byte_len;
if (cur_asm_state != ASM_UNPACK)
{
as_bad ("`.endunpack' has no matching `unpack' instruction");
return;
}
byte_len = cur_vif_insn_length ();
#if 0 /* unpack doesn't support prespecifying a length */
if (cur_varlen_value * 16 != bytelen)
as_warn ("length in `direct' instruction does not match length of data");
#endif
if (output_vif)
install_vif_length (cur_varlen_insn, byte_len);
cur_asm_state = ASM_INIT;
/* These needn't be reset, but to catch bugs they are. */
cur_varlen_frag = NULL;
cur_varlen_insn = NULL;
cur_varlen_value = 0;
/* Update $.UnpackLoc. */
vif_set_unpackloc (vif_get_unpackloc () + byte_len);
demand_empty_rest_of_line ();
}
static void
s_state (state)
int state;
@ -1908,10 +1982,10 @@ s_state (state)
/* If in MPG state and the user requests to change to VU state,
leave the state as MPG. This happens when we see an mpg followed
by a .include that has .vu. */
if (cur_asm_state == ASM_MPG && state == ASM_VU)
if (CUR_ASM_STATE == ASM_MPG && state == ASM_VU)
return;
cur_asm_state = state;
set_asm_state (state);
demand_empty_rest_of_line ();
}