}
arch_entry;
+/* Modes for parse_insn() to operate in. */
+enum parse_mode {
+ parse_all,
+ parse_prefix,
+ parse_pseudo_prefix,
+};
+
static void update_code_flag (int, int);
static void s_insn (int);
static void s_noopt (int);
static int i386_intel_simplify (expressionS *);
static int i386_intel_parse_name (const char *, expressionS *);
static const reg_entry *parse_register (const char *, char **);
-static const char *parse_insn (const char *, char *, bool);
+static const char *parse_insn (const char *, char *, enum parse_mode);
static char *parse_operands (char *, const char *);
static void swap_operands (void);
static void swap_2_operands (unsigned int, unsigned int);
void
md_begin (void)
{
- /* Support pseudo prefixes like {disp32}. */
- lex_type ['{'] = LEX_BEGIN_NAME;
+ /* Make sure possible padding space is clear. */
+ memset (&pp, 0, sizeof (pp));
/* Initialize op_hash hash table. */
op_hash = str_htab_create ();
unsigned int j;
memset (&i, '\0', sizeof (i));
- memset (&pp, 0, sizeof (pp));
i.rounding.type = rc_none;
for (j = 0; j < MAX_OPERANDS; j++)
i.reloc[j] = NO_RELOC;
machine dependent instruction. This function is supposed to emit
the frags/bytes it assembles to. */
-void
-md_assemble (char *line)
+static void
+i386_assemble (char *line)
{
unsigned int j;
char mnemonic[MAX_MNEM_SIZE], mnem_suffix = 0, *copy = NULL;
char *xstrdup_copy = NULL;
const char *end, *pass1_mnem = NULL;
enum i386_error pass1_err = 0;
+ struct pseudo_prefixes orig_pp = pp;
const insn_template *t;
struct last_insn *last_insn
= &seg_info(now_seg)->tc_segment_info_data.last_insn;
We assume that the scrubber has arranged it so that line[0] is the valid
start of a (possibly prefixed) mnemonic. */
- end = parse_insn (line, mnemonic, false);
+ end = parse_insn (line, mnemonic, parse_all);
if (end == NULL)
{
if (pass1_mnem != NULL)
no_match:
pass1_err = i.error;
pass1_mnem = insn_name (current_templates.start);
+ pp = orig_pp;
goto retry;
}
last_insn->kind = last_insn_other;
}
+void
+md_assemble (char *line)
+{
+ i386_assemble (line);
+ current_templates.start = NULL;
+ memset (&pp, 0, sizeof (pp));
+}
+
/* The Q suffix is generally valid only in 64-bit mode, with very few
exceptions: fild, fistp, fisttp, and cmpxchg8b. Note that for fild
and fisttp only one of their two templates is matched below: That's
}
static const char *
-parse_insn (const char *line, char *mnemonic, bool prefix_only)
+parse_insn (const char *line, char *mnemonic, enum parse_mode mode)
{
const char *l = line, *token_start = l;
char *mnem_p;
++mnem_p;
++l;
}
+ else if (mode == parse_pseudo_prefix)
+ break;
while ((*mnem_p = mnemonic_chars[(unsigned char) *l]) != 0)
{
if (*mnem_p == '.')
&& (intel_syntax
|| (*l != PREFIX_SEPARATOR && *l != ',')))
{
- if (prefix_only)
+ if (mode != parse_all)
break;
as_bad (_("invalid character %s in mnemonic"),
output_invalid (*l));
break;
}
- if (prefix_only)
+ if (mode != parse_all)
return token_start;
if (!current_templates.start)
i.op[0].imms, 0, reloc (2, 0, 0, i.reloc[0]));
}
+/* Hook used to reject pseudo-prefixes misplaced at the start of a line. */
+
+void i386_start_line (void)
+{
+ struct pseudo_prefixes last_pp;
+
+ memcpy (&last_pp, &pp, sizeof (pp));
+ memset (&pp, 0, sizeof (pp));
+ if (memcmp (&pp, &last_pp, sizeof (pp)))
+ as_bad_where (frag_now->fr_file, frag_now->fr_line,
+ _("pseudo prefix without instruction"));
+}
+
+/* Hook used to warn about pseudo-prefixes ahead of a label. */
+
+bool i386_check_label (void)
+{
+ struct pseudo_prefixes last_pp;
+
+ memcpy (&last_pp, &pp, sizeof (pp));
+ memset (&pp, 0, sizeof (pp));
+ if (memcmp (&pp, &last_pp, sizeof (pp)))
+ as_warn (_("pseudo prefix ahead of label; ignoring"));
+ return true;
+}
+
+/* Hook used to parse pseudo-prefixes off of the start of a line. */
+
+int
+i386_unrecognized_line (int ch)
+{
+ char mnemonic[MAX_MNEM_SIZE];
+ const char *end;
+
+ if (ch != '{')
+ return 0;
+
+ --input_line_pointer;
+ know (*input_line_pointer == ch);
+
+ end = parse_insn (input_line_pointer, mnemonic, parse_pseudo_prefix);
+ if (end == NULL)
+ {
+ /* Diagnostic was already issued. */
+ ignore_rest_of_line ();
+ memset (&pp, 0, sizeof (pp));
+ return 1;
+ }
+
+ if (end == input_line_pointer)
+ {
+ ++input_line_pointer;
+ return 0;
+ }
+
+ input_line_pointer += end - input_line_pointer;
+ return 1;
+}
+
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
void
x86_cleanup (void)
saved_char = *saved_ilp;
*saved_ilp = 0;
- end = parse_insn (line, mnemonic, true);
+ end = parse_insn (line, mnemonic, parse_prefix);
if (end == NULL)
{
bad:
*saved_ilp = saved_char;
ignore_rest_of_line ();
i.tm.mnem_off = 0;
+ memset (&pp, 0, sizeof (pp));
return;
}
line += end - line;
/* Make sure dot_insn() won't yield "true" anymore. */
i.tm.mnem_off = 0;
+
+ current_templates.start = NULL;
+ memset (&pp, 0, sizeof (pp));
}
#ifdef TE_PE
if (vector_size < VSZ512)
return false;
- switch (pp.encoding)
+ /* Don't update pp when not dealing with insn operands. */
+ switch (current_templates.start ? pp.encoding : encoding_evex)
{
case encoding_default:
case encoding_egpr:
|| flag_code != CODE_64BIT)
return false;
- switch (pp.encoding)
+ /* Don't update pp when not dealing with insn operands. */
+ switch (current_templates.start ? pp.encoding : encoding_evex)
{
case encoding_default:
case encoding_egpr:
|| flag_code != CODE_64BIT)
return false;
- switch (pp.encoding)
+ /* Don't update pp when not dealing with insn operands. */
+ switch (current_templates.start ? pp.encoding : encoding_egpr)
{
case encoding_default:
pp.encoding = encoding_egpr;