Allowed state transitions:
ASM_INIT <--> ASM_MPG
ASM_DIRECT <--> ASM_GIF
- ASM_UNPACK
+ ASM_UNPACK <--> ASM_GIF
ASM_VU
+ ASM_GIF
FIXME: Make the ASM_INIT -> ASM_VU a one way transition.
".vu" must be seen at the top of the file,
*/
typedef enum {
- ASM_INIT, ASM_DIRECT, ASM_MPG, ASM_UNPACK, ASM_VU, ASM_GIF
+ ASM_INIT, ASM_DIRECT, ASM_MPG, ASM_UNPACK, ASM_VU, ASM_GIF, ASM_MAX
} asm_state;
/* We need to maintain a stack of the current and previous status to handle
#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;
+static int cur_state_level;
/* Macro to fetch the current state. */
-#define CUR_ASM_STATE (asm_state_stack[cur_state_index])
+#define CUR_ASM_STATE (asm_state_stack[cur_state_level])
/* 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));
+static void set_asm_state PARAMS ((asm_state, const char *));
/* Set to non-zero if any non-vu insn seen.
Used to control type of relocations emitted. */
static void s_endmpg PARAMS ((int));
static void s_endunpack PARAMS ((int));
static void s_endgif PARAMS ((int));
-static void s_state PARAMS ((int));
+static void s_vu PARAMS ((int));
static void s_dvp_func PARAMS ((int));
/* The target specific pseudo-ops which we support. */
{ "endmpg", s_endmpg, ENDMPG_USER },
{ "endunpack", s_endunpack, 0 },
{ "endgif", s_endgif, 0 },
- { "vu", s_state, ASM_VU },
+ { "vu", s_vu, 0 },
/* We need to intercept .func/.endfunc so that we can prepend _$.
??? Not sure this is right though as _$foo is the lma version. */
{ "func", s_dvp_func, 0 },
force_mach_label ();
/* Initialize the parsing state. */
- cur_state_index = 0;
- set_asm_state (ASM_INIT);
+ set_asm_state (ASM_INIT, NULL);
/* Pack vif insns in dma tags by default. */
dma_pack_vif_p = 1;
{
as_bad ("missing .endgif");
pop_asm_state (1);
+ /* We still parse the instruction. */
}
- /* 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)
{
assemble_vif (str);
non_vu_insn_seen_p = 1;
}
- else if (CUR_ASM_STATE == ASM_DIRECT)
+ else if (CUR_ASM_STATE == ASM_DIRECT
+ || CUR_ASM_STATE == ASM_UNPACK)
{
assemble_gif (str);
non_vu_insn_seen_p = 1;
if (opcode->flags & VIF_OPCODE_MPG)
{
record_mach (DVP_VUUP, 1);
- set_asm_state (ASM_MPG);
+ set_asm_state (ASM_MPG, "mpg");
byte_len = insert_file (file, insert_mpg_marker, 0, 256 * 8);
s_endmpg (ENDMPG_INTERNAL);
}
else if (opcode->flags & VIF_OPCODE_DIRECT)
{
record_mach (DVP_GIF, 1);
- set_asm_state (ASM_DIRECT);
+ set_asm_state (ASM_DIRECT, "direct");
byte_len = insert_file (file, NULL, 0, 0);
s_enddirect (1);
}
else if (opcode->flags & VIF_OPCODE_UNPACK)
{
int max_len = 0; /*unpack_max_byte_len (insn_buf[0]);*/
- set_asm_state (ASM_UNPACK);
+ set_asm_state (ASM_UNPACK, "unpack");
byte_len = insert_file (file, NULL /*insert_unpack_marker*/,
insn_buf[0], max_len);
s_endunpack (1);
if (opcode->flags & VIF_OPCODE_MPG)
{
- set_asm_state (ASM_MPG);
+ set_asm_state (ASM_MPG, "mpg");
/* Enable automatic mpg insertion every 256 insns. */
vu_count = 0;
}
else if (opcode->flags & VIF_OPCODE_DIRECT)
- set_asm_state (ASM_DIRECT);
+ set_asm_state (ASM_DIRECT, "direct");
else if (opcode->flags & VIF_OPCODE_UNPACK)
- set_asm_state (ASM_UNPACK);
+ set_asm_state (ASM_UNPACK, "unpack");
}
}
}
-/* Subroutine of md_assemble to assemble GIF instructions. */
+/* Subroutine of md_assemble to assemble GIF instructions.
+ We assume CUR_ASM_STATE is one of ASM_{INIT,DIRECT,UNPACK}. */
static void
assemble_gif (str)
return 1;
}
-/* Push/pop the current parsing state. */
+/* Push the current parsing state to NEW_STATE. */
static void
push_asm_state (new_state)
asm_state new_state;
{
- ++cur_state_index;
- if (cur_state_index == MAX_STATE_DEPTH)
+ asm_state cur_state = CUR_ASM_STATE;
+
+ ++cur_state_level;
+ if (cur_state_level == MAX_STATE_DEPTH)
as_fatal ("internal error: unexpected state push");
- asm_state_stack[cur_state_index] = new_state;
+ asm_state_stack[cur_state_level] = 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. */
+ If so we reset the state to ASM_INIT. */
static void
pop_asm_state (top_ok_p)
int top_ok_p;
{
- if (cur_state_index == 0)
+ if (cur_state_level == 0)
{
- if (top_ok_p)
- asm_state_stack[cur_state_index] = ASM_INIT;
- else
+ if (! top_ok_p)
as_fatal ("internal error: unexpected state pop");
+ CUR_ASM_STATE = ASM_INIT;
}
else
- --cur_state_index;
+ --cur_state_level;
}
+/* Set the top level assembler state. */
+
static void
-set_asm_state (state)
+set_asm_state (state, insn_name)
asm_state state;
+ const char *insn_name;
{
+ if (insn_name)
+ {
+ if (CUR_ASM_STATE != ASM_INIT)
+ as_bad ("illegal place for `%s' instruction", insn_name);
+ }
+ cur_state_level = 0;
CUR_ASM_STATE = state;
}
\f
/* Advance over the '*'. */
++input_line_pointer;
+ return;
}
}
}
}
+ /* ??? It might be cleaner to not do this at all here (when ! fx_done)
+ and leave it to bfd_install_relocation. */
+ if ((operand->flags & DVP_OPERAND_RELOC_U15_S3) != 0)
+ value >>= 3;
+ else if ((operand->flags & DVP_OPERAND_RELOC_11_S4) != 0)
+ value >>= 4;
+
/* Fetch the instruction, insert the fully resolved operand
value, and stuff the instruction back again. The fixup is recorded
at the appropriate word so pass DVP_MOD_THIS_WORD so any offset
&& operand->shift == 4);
fixP->fx_r_type = BFD_RELOC_MIPS_DVP_27_S4;
}
+ else if ((operand->flags & DVP_OPERAND_RELOC_11_S4) != 0)
+ {
+ assert (operand->bits == 11
+ && operand->shift == 0);
+ fixP->fx_r_type = BFD_RELOC_MIPS_DVP_11_S4;
+ /* ??? bfd_install_relocation will duplicate what we've done to
+ install the addend, so tell it not to. This is an instance
+ where setting partial_inplace to true has some use. */
+ value = 0;
+ }
+ else if ((operand->flags & DVP_OPERAND_RELOC_U15_S3) != 0)
+ {
+ assert (operand->bits == 15
+ && operand->shift == 0);
+ fixP->fx_r_type = BFD_RELOC_MIPS_DVP_U15_S3;
+ /* ??? bfd_install_relocation will duplicate what we've done to
+ install the addend, so tell it not to. This is an instance
+ where setting partial_inplace to true has some use. */
+ value = 0;
+ }
else
{
as_bad_where (fixP->fx_file, fixP->fx_line,
char **pstr;
const char **errmsg;
{
- LITTLENUM_TYPE words[MAX_LITTLENUMS];
- char *p;
-
- p = atof_ieee (*pstr, 'f', words);
- *pstr = p;
- return (words[0] << 16) | words[1];
+ if ((*pstr)[0] == '0'
+ && ((*pstr)[1] == 'x' || (*pstr)[1] == 'X'))
+ {
+ long value;
+ (*pstr) += 2;
+ value = strtol (*pstr, pstr, 16);
+ return value;
+ }
+ else
+ {
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ *pstr = atof_ieee (*pstr, 'f', words);
+ return (words[0] << 16) | words[1];
+ }
}
/* Scan a symbol and return a pointer to one past the end. */
vif_data_end->sy_frag = frag_now;
S_SET_VALUE (vif_data_end, (valueT) frag_now_fix ());
- set_asm_state (ASM_INIT);
+ pop_asm_state (1);
/* Needn't be reset, but to catch bugs it is. */
vif_data_end = NULL;
double words in this chunk. */
mpgloc_sym = compute_mpgloc (mpgloc_sym, vif_data_start, vif_data_end);
- set_asm_state (ASM_INIT);
+ pop_asm_state (1);
/* Needn't be reset, but to catch bugs it is. */
vif_data_end = NULL;
/* Round up to next word boundary. */
frag_align (2, 0, 0);
- set_asm_state (ASM_INIT);
+ pop_asm_state (1);
/* Needn't be reset, but to catch bugs it is. */
vif_data_end = NULL;
as_bad (".endgif doesn't follow a gif tag");
return;
}
- pop_asm_state (0);
+ pop_asm_state (1);
/* Fill out to proper boundary.
??? This may cause eval_expr to always queue a fixup. So be it. */
}
static void
-s_state (state)
- int state;
+s_vu (ignore)
+ int ignore;
{
/* 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. Note that no attempt is made to support
an include depth > 1 for this case. */
- if (CUR_ASM_STATE == ASM_MPG && state == ASM_VU)
+ if (CUR_ASM_STATE == ASM_MPG)
return;
- /* If changing to the VU state, we need to set up things for $.mpgloc
- calculations. */
- if (state == ASM_VU)
- {
- /* FIXME: May need to check that we're not clobbering currently
- in use versions of these. Also need to worry about which section
- the .vu is issued in. On the other hand, ".vu" isn't intended
- to be supported everywhere. */
- vif_data_start = expr_build_dot ();
- mpgloc_sym = expr_build_uconstant (0);
+ /* We need to set up things for $.mpgloc calculations. */
+ /* FIXME: May need to check that we're not clobbering currently
+ in use versions of these. Also need to worry about which section
+ the .vu is issued in. On the other hand, ".vu" isn't intended
+ to be supported everywhere. */
+ vif_data_start = expr_build_dot ();
+ mpgloc_sym = expr_build_uconstant (0);
#if 0 /* ??? wip */
- create_vuoverlay_section (vuoverlay_section_name (NULL), mpgloc_sym,
- NULL, NULL);
+ create_vuoverlay_section (vuoverlay_section_name (NULL), mpgloc_sym,
+ NULL, NULL);
#endif
- }
- set_asm_state (state);
+ set_asm_state (ASM_VU, ".vu");
demand_empty_rest_of_line ();
}