gas: sparc: fix collision of registers and pseudo-ops.

The current sparc assembler breaks when the name of an ancillary-state
register, privileged register or hyperprivileged register has a
%-pseudo-operation name as a prefix.  For example, %hmcdper and %hm(),
or %hintp and %hi().

This patch fixes it by introducing a new table `perc_table' (for
%-table) that contains an entry for every %name supported by the
assembler, other than the general registers.  This table is used to
detect name collisions when the assembler tries to detect a %-pseudo-op.

This patch also fixes a related bug, making sure that v9a_asr_table and
hpriv_reg_table are sorted in reverse lexicographic order, as otherwise
the search code may fail.

gas/ChangeLog:

2016-06-17  Jose E. Marchesi  <jose.marchesi@oracle.com>

	* config/tc-sparc.c (priv_reg_table): Use NULL instead of the
	empty string to mark the end of the array.
	(hpriv_reg_table): Likewise.
	(v9a_asr_table): Likewise.
	(cmp_reg_entry): Handle entries with NULL names.
	(F_POP_V9): Define.
	(F_POP_PCREL): Likewise.
	(F_POP_TLS_CALL): Likewise.
	(F_POP_POSTFIX): Likewise.
	(struct pop_entry): New type.
	(pop_table): New variable.
	(enum pop_entry_type): New type.
	(struct perc_entry): Likewise.
	(NUM_PERC_ENTRIES): Define.
	(perc_table): New variable.
	(cmp_perc_entry): New function.
	(md_begin): Sort hpriv_reg_table and v9a_asr_table, and initialize
	perc_table.
	(sparc_ip): Handle entries with NULL names in priv_reg_table,
	hpriv_reg_table and v9a_asr_table.  Use perc_table to handle
	%-pseudo-ops.
This commit is contained in:
Jose E. Marchesi
2016-06-17 02:13:30 -07:00
parent 4f26fb3a1b
commit 8b8c7c9f49
2 changed files with 263 additions and 140 deletions

@ -1,3 +1,27 @@
2016-06-17 Jose E. Marchesi <jose.marchesi@oracle.com>
* config/tc-sparc.c (priv_reg_table): Use NULL instead of the
empty string to mark the end of the array.
(hpriv_reg_table): Likewise.
(v9a_asr_table): Likewise.
(cmp_reg_entry): Handle entries with NULL names.
(F_POP_V9): Define.
(F_POP_PCREL): Likewise.
(F_POP_TLS_CALL): Likewise.
(F_POP_POSTFIX): Likewise.
(struct pop_entry): New type.
(pop_table): New variable.
(enum pop_entry_type): New type.
(struct perc_entry): Likewise.
(NUM_PERC_ENTRIES): Define.
(perc_table): New variable.
(cmp_perc_entry): New function.
(md_begin): Sort hpriv_reg_table and v9a_asr_table, and initialize
perc_table.
(sparc_ip): Handle entries with NULL names in priv_reg_table,
hpriv_reg_table and v9a_asr_table. Use perc_table to handle
%-pseudo-ops.
2016-06-15 Nick Clifton <nickc@redhat.com> 2016-06-15 Nick Clifton <nickc@redhat.com>
* config/tc-ft32.c (md_assemble): Call dwarf2_emit_insn with the * config/tc-ft32.c (md_assemble): Call dwarf2_emit_insn with the

@ -807,7 +807,7 @@ struct priv_reg_entry priv_reg_table[] =
{"gl", 16}, {"gl", 16},
{"pmcdper", 23}, {"pmcdper", 23},
{"ver", 31}, {"ver", 31},
{"", -1}, /* End marker. */ {NULL, -1}, /* End marker. */
}; };
struct priv_reg_entry hpriv_reg_table[] = struct priv_reg_entry hpriv_reg_table[] =
@ -820,11 +820,10 @@ struct priv_reg_entry hpriv_reg_table[] =
{"hstick_offset", 28}, {"hstick_offset", 28},
{"hstick_enable", 29}, {"hstick_enable", 29},
{"hstick_cmpr", 31}, {"hstick_cmpr", 31},
{"", -1}, /* End marker. */ {NULL, -1}, /* End marker. */
}; };
/* v9a specific asrs. This table is ordered by initial /* v9a or later specific ancillary state registers. */
letter, in reverse. */
struct priv_reg_entry v9a_asr_table[] = struct priv_reg_entry v9a_asr_table[] =
{ {
@ -845,7 +844,7 @@ struct priv_reg_entry v9a_asr_table[] =
{"dcr", 18}, {"dcr", 18},
{"cfr", 26}, {"cfr", 26},
{"clear_softint", 21}, {"clear_softint", 21},
{"", -1}, /* End marker. */ {NULL, -1}, /* End marker. */
}; };
static int static int
@ -854,7 +853,131 @@ cmp_reg_entry (const void *parg, const void *qarg)
const struct priv_reg_entry *p = (const struct priv_reg_entry *) parg; const struct priv_reg_entry *p = (const struct priv_reg_entry *) parg;
const struct priv_reg_entry *q = (const struct priv_reg_entry *) qarg; const struct priv_reg_entry *q = (const struct priv_reg_entry *) qarg;
return strcmp (q->name, p->name); if (p->name == q->name)
return 0;
else if (p->name == NULL)
return 1;
else if (q->name == NULL)
return -1;
else
return strcmp (q->name, p->name);
}
/* sparc %-pseudo-operations. */
#define F_POP_V9 0x1 /* The pseudo-op is for v9 only. */
#define F_POP_PCREL 0x2 /* The pseudo-op can be used in pc-relative
contexts. */
#define F_POP_TLS_CALL 0x4 /* The pseudo-op marks a tls call. */
#define F_POP_POSTFIX 0x8 /* The pseudo-op should appear after the
last operand of an
instruction. (Generally they can appear
anywhere an immediate operand is
expected. */
struct pop_entry
{
/* The name as it appears in assembler. */
const char *name;
/* The reloc this pseudo-op translates to. */
int reloc;
/* Flags. See F_POP_* above. */
int flags;
};
struct pop_entry pop_table[] =
{
{ "hix", BFD_RELOC_SPARC_HIX22, F_POP_V9 },
{ "lox", BFD_RELOC_SPARC_LOX10, F_POP_V9 },
{ "hi", BFD_RELOC_HI22, F_POP_PCREL },
{ "lo", BFD_RELOC_LO10, F_POP_PCREL },
{ "pc22", BFD_RELOC_SPARC_PC22, F_POP_PCREL },
{ "pc10", BFD_RELOC_SPARC_PC10, F_POP_PCREL },
{ "hh", BFD_RELOC_SPARC_HH22, F_POP_V9|F_POP_PCREL },
{ "hm", BFD_RELOC_SPARC_HM10, F_POP_V9|F_POP_PCREL },
{ "lm", BFD_RELOC_SPARC_LM22, F_POP_V9|F_POP_PCREL },
{ "h34", BFD_RELOC_SPARC_H34, F_POP_V9 },
{ "l34", BFD_RELOC_SPARC_L44, F_POP_V9 },
{ "h44", BFD_RELOC_SPARC_H44, F_POP_V9 },
{ "m44", BFD_RELOC_SPARC_M44, F_POP_V9 },
{ "l44", BFD_RELOC_SPARC_L44, F_POP_V9 },
{ "uhi", BFD_RELOC_SPARC_HH22, F_POP_V9 },
{ "ulo", BFD_RELOC_SPARC_HM10, F_POP_V9 },
{ "tgd_hi22", BFD_RELOC_SPARC_TLS_GD_HI22, 0 },
{ "tgd_lo10", BFD_RELOC_SPARC_TLS_GD_LO10, 0 },
{ "tldm_hi22", BFD_RELOC_SPARC_TLS_LDM_HI22, 0 },
{ "tldm_lo10", BFD_RELOC_SPARC_TLS_LDM_LO10, 0 },
{ "tldo_hix22", BFD_RELOC_SPARC_TLS_LDO_HIX22, 0 },
{ "tldo_lox10", BFD_RELOC_SPARC_TLS_LDO_LOX10, 0 },
{ "tie_hi22", BFD_RELOC_SPARC_TLS_IE_HI22, 0 },
{ "tie_lo10", BFD_RELOC_SPARC_TLS_IE_LO10, 0 },
{ "tle_hix22", BFD_RELOC_SPARC_TLS_LE_HIX22, 0 },
{ "tle_lox10", BFD_RELOC_SPARC_TLS_LE_LOX10, 0 },
{ "gdop_hix22", BFD_RELOC_SPARC_GOTDATA_OP_HIX22, 0 },
{ "gdop_lox10", BFD_RELOC_SPARC_GOTDATA_OP_LOX10, 0 },
{ "tgd_add", BFD_RELOC_SPARC_TLS_GD_ADD, F_POP_POSTFIX },
{ "tgd_call", BFD_RELOC_SPARC_TLS_GD_CALL, F_POP_POSTFIX|F_POP_TLS_CALL },
{ "tldm_add", BFD_RELOC_SPARC_TLS_LDM_ADD, F_POP_POSTFIX },
{ "tldm_call", BFD_RELOC_SPARC_TLS_LDM_CALL, F_POP_POSTFIX|F_POP_TLS_CALL },
{ "tldo_add", BFD_RELOC_SPARC_TLS_LDO_ADD, F_POP_POSTFIX },
{ "tie_ldx", BFD_RELOC_SPARC_TLS_IE_LDX, F_POP_POSTFIX },
{ "tie_ld", BFD_RELOC_SPARC_TLS_IE_LD, F_POP_POSTFIX },
{ "tie_add", BFD_RELOC_SPARC_TLS_IE_ADD, F_POP_POSTFIX },
{ "gdop", BFD_RELOC_SPARC_GOTDATA_OP, F_POP_POSTFIX },
{ NULL, 0, 0 },
};
/* Table of %-names that can appear in a sparc assembly program. This
table is initialized in md_begin and contains entries for each
privileged/hyperprivileged/alternate register and %-pseudo-op. */
enum perc_entry_type
{
perc_entry_none = 0,
perc_entry_reg,
perc_entry_post_pop,
perc_entry_imm_pop
};
struct perc_entry
{
/* Entry type. */
enum perc_entry_type type;
/* Name of the %-entity. */
const char *name;
/* strlen (name). */
int len;
/* Value. Either a pop or a reg depending on type.*/
union
{
struct pop_entry *pop;
struct priv_reg_entry *reg;
};
};
#define NUM_PERC_ENTRIES \
(((sizeof (priv_reg_table) / sizeof (priv_reg_table[0])) - 1) \
+ ((sizeof (hpriv_reg_table) / sizeof (hpriv_reg_table[0])) - 1) \
+ ((sizeof (v9a_asr_table) / sizeof (v9a_asr_table[0])) - 1) \
+ ((sizeof (pop_table) / sizeof (pop_table[0])) - 1) \
+ 1)
struct perc_entry perc_table[NUM_PERC_ENTRIES];
static int
cmp_perc_entry (const void *parg, const void *qarg)
{
const struct perc_entry *p = (const struct perc_entry *) parg;
const struct perc_entry *q = (const struct perc_entry *) qarg;
if (p->name == q->name)
return 0;
else if (p->name == NULL)
return 1;
else if (q->name == NULL)
return -1;
else
return strcmp (q->name, p->name);
} }
/* This function is called once, at assembler startup time. It should /* This function is called once, at assembler startup time. It should
@ -932,7 +1055,11 @@ md_begin (void)
qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]), qsort (priv_reg_table, sizeof (priv_reg_table) / sizeof (priv_reg_table[0]),
sizeof (priv_reg_table[0]), cmp_reg_entry); sizeof (priv_reg_table[0]), cmp_reg_entry);
qsort (hpriv_reg_table, sizeof (hpriv_reg_table) / sizeof (hpriv_reg_table[0]),
sizeof (hpriv_reg_table[0]), cmp_reg_entry);
qsort (v9a_asr_table, sizeof (v9a_asr_table) / sizeof (v9a_asr_table[0]),
sizeof (v9a_asr_table[0]), cmp_reg_entry);
/* If -bump, record the architecture level at which we start issuing /* If -bump, record the architecture level at which we start issuing
warnings. The behaviour is different depending upon whether an warnings. The behaviour is different depending upon whether an
architecture was explicitly specified. If it wasn't, we issue warnings architecture was explicitly specified. If it wasn't, we issue warnings
@ -964,6 +1091,50 @@ md_begin (void)
current_max_architecture)) current_max_architecture))
break; break;
} }
/* Prepare the tables of %-pseudo-ops. */
{
struct priv_reg_entry *reg_tables[]
= {priv_reg_table, hpriv_reg_table, v9a_asr_table, NULL};
struct priv_reg_entry **reg_table;
int entry = 0;
/* Add registers. */
for (reg_table = reg_tables; reg_table[0]; reg_table++)
{
struct priv_reg_entry *reg;
for (reg = *reg_table; reg->name; reg++)
{
struct perc_entry *p = &perc_table[entry++];
p->type = perc_entry_reg;
p->name = reg->name;
p->len = strlen (reg->name);
p->reg = reg;
}
}
/* Add %-pseudo-ops. */
{
struct pop_entry *pop;
for (pop = pop_table; pop->name; pop++)
{
struct perc_entry *p = &perc_table[entry++];
p->type = (pop->flags & F_POP_POSTFIX
? perc_entry_post_pop : perc_entry_imm_pop);
p->name = pop->name;
p->len = strlen (pop->name);
p->pop = pop;
}
}
/* Last entry is the centinel. */
perc_table[entry].type = perc_entry_none;
qsort (perc_table, sizeof (perc_table) / sizeof (perc_table[0]),
sizeof (perc_table[0]), cmp_perc_entry);
}
} }
/* Called after all assembly has been done. */ /* Called after all assembly has been done. */
@ -1709,20 +1880,19 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
/* Parse a sparc64 privileged register. */ /* Parse a sparc64 privileged register. */
if (*s == '%') if (*s == '%')
{ {
struct priv_reg_entry *p = priv_reg_table; struct priv_reg_entry *p;
unsigned int len = 9999999; /* Init to make gcc happy. */ unsigned int len = 9999999; /* Init to make gcc happy. */
s += 1; s += 1;
while (p->name[0] > s[0]) for (p = priv_reg_table; p->name; p++)
p++; if (p->name[0] == s[0])
while (p->name[0] == s[0]) {
{ len = strlen (p->name);
len = strlen (p->name); if (strncmp (p->name, s, len) == 0)
if (strncmp (p->name, s, len) == 0) break;
break; }
p++;
} if (!p->name)
if (p->name[0] != s[0])
{ {
error_message = _(": unrecognizable privileged register"); error_message = _(": unrecognizable privileged register");
goto error; goto error;
@ -1745,20 +1915,19 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
/* Parse a sparc64 hyperprivileged register. */ /* Parse a sparc64 hyperprivileged register. */
if (*s == '%') if (*s == '%')
{ {
struct priv_reg_entry *p = hpriv_reg_table; struct priv_reg_entry *p;
unsigned int len = 9999999; /* Init to make gcc happy. */ unsigned int len = 9999999; /* Init to make gcc happy. */
s += 1; s += 1;
while (p->name[0] > s[0]) for (p = hpriv_reg_table; p->name; p++)
p++; if (p->name[0] == s[0])
while (p->name[0] == s[0]) {
{ len = strlen (p->name);
len = strlen (p->name); if (strncmp (p->name, s, len) == 0)
if (strncmp (p->name, s, len) == 0) break;
break; }
p++;
} if (!p->name)
if (p->name[0] != s[0])
{ {
error_message = _(": unrecognizable hyperprivileged register"); error_message = _(": unrecognizable hyperprivileged register");
goto error; goto error;
@ -1781,20 +1950,19 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
/* Parse a v9a/v9b ancillary state register. */ /* Parse a v9a/v9b ancillary state register. */
if (*s == '%') if (*s == '%')
{ {
struct priv_reg_entry *p = v9a_asr_table; struct priv_reg_entry *p;
unsigned int len = 9999999; /* Init to make gcc happy. */ unsigned int len = 9999999; /* Init to make gcc happy. */
s += 1; s += 1;
while (p->name[0] > s[0]) for (p = v9a_asr_table; p->name; p++)
p++; if (p->name[0] == s[0])
while (p->name[0] == s[0]) {
{ len = strlen (p->name);
len = strlen (p->name); if (strncmp (p->name, s, len) == 0)
if (strncmp (p->name, s, len) == 0) break;
break; }
p++;
} if (!p->name)
if (p->name[0] != s[0])
{ {
error_message = _(": unrecognizable v9a or v9b ancillary state register"); error_message = _(": unrecognizable v9a or v9b ancillary state register");
goto error; goto error;
@ -2062,67 +2230,45 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
case '\0': /* End of args. */ case '\0': /* End of args. */
if (s[0] == ',' && s[1] == '%') if (s[0] == ',' && s[1] == '%')
{ {
static const struct ops
{
/* The name as it appears in assembler. */
const char *name;
/* strlen (name), precomputed for speed */
int len;
/* The reloc this pseudo-op translates to. */
int reloc;
/* 1 if tls call. */
int tls_call;
}
ops[] =
{
{ "tgd_add", 7, BFD_RELOC_SPARC_TLS_GD_ADD, 0 },
{ "tgd_call", 8, BFD_RELOC_SPARC_TLS_GD_CALL, 1 },
{ "tldm_add", 8, BFD_RELOC_SPARC_TLS_LDM_ADD, 0 },
{ "tldm_call", 9, BFD_RELOC_SPARC_TLS_LDM_CALL, 1 },
{ "tldo_add", 8, BFD_RELOC_SPARC_TLS_LDO_ADD, 0 },
{ "tie_ldx", 7, BFD_RELOC_SPARC_TLS_IE_LDX, 0 },
{ "tie_ld", 6, BFD_RELOC_SPARC_TLS_IE_LD, 0 },
{ "tie_add", 7, BFD_RELOC_SPARC_TLS_IE_ADD, 0 },
{ "gdop", 4, BFD_RELOC_SPARC_GOTDATA_OP, 0 },
{ NULL, 0, 0, 0 }
};
const struct ops *o;
char *s1; char *s1;
int npar = 0; int npar = 0;
const struct perc_entry *p;
for (o = ops; o->name; o++) for (p = perc_table; p->type != perc_entry_none; p++)
if (strncmp (s + 2, o->name, o->len) == 0) if ((p->type == perc_entry_post_pop || p->type == perc_entry_reg)
break; && strncmp (s + 2, p->name, p->len) == 0)
if (o->name == NULL) break;
break; if (p->type == perc_entry_none || p->type == perc_entry_reg)
break;
if (s[o->len + 2] != '(') if (s[p->len + 2] != '(')
{ {
as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name); as_bad (_("Illegal operands: %%%s requires arguments in ()"), p->name);
return special_case; return special_case;
} }
if (! o->tls_call && the_insn.reloc != BFD_RELOC_NONE) if (! (p->pop->flags & F_POP_TLS_CALL)
&& the_insn.reloc != BFD_RELOC_NONE)
{ {
as_bad (_("Illegal operands: %%%s cannot be used together with other relocs in the insn ()"), as_bad (_("Illegal operands: %%%s cannot be used together with other relocs in the insn ()"),
o->name); p->name);
return special_case; return special_case;
} }
if (o->tls_call if ((p->pop->flags & F_POP_TLS_CALL)
&& (the_insn.reloc != BFD_RELOC_32_PCREL_S2 && (the_insn.reloc != BFD_RELOC_32_PCREL_S2
|| the_insn.exp.X_add_number != 0 || the_insn.exp.X_add_number != 0
|| the_insn.exp.X_add_symbol || the_insn.exp.X_add_symbol
!= symbol_find_or_make ("__tls_get_addr"))) != symbol_find_or_make ("__tls_get_addr")))
{ {
as_bad (_("Illegal operands: %%%s can be only used with call __tls_get_addr"), as_bad (_("Illegal operands: %%%s can be only used with call __tls_get_addr"),
o->name); p->name);
return special_case; return special_case;
} }
the_insn.reloc = o->reloc; the_insn.reloc = p->pop->reloc;
memset (&the_insn.exp, 0, sizeof (the_insn.exp)); memset (&the_insn.exp, 0, sizeof (the_insn.exp));
s += o->len + 3; s += p->len + 3;
for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++) for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)
if (*s1 == '(') if (*s1 == '(')
@ -2136,7 +2282,7 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
if (*s1 != ')') if (*s1 != ')')
{ {
as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name); as_bad (_("Illegal operands: %%%s requires arguments in ()"), p->name);
return special_case; return special_case;
} }
@ -2525,72 +2671,25 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
/* Check for %hi, etc. */ /* Check for %hi, etc. */
if (*s == '%') if (*s == '%')
{ {
static const struct ops { const struct perc_entry *p;
/* The name as it appears in assembler. */
const char *name; for (p = perc_table; p->type != perc_entry_none; p++)
/* strlen (name), precomputed for speed */ if ((p->type == perc_entry_imm_pop || p->type == perc_entry_reg)
int len; && strncmp (s + 1, p->name, p->len) == 0)
/* The reloc this pseudo-op translates to. */ break;
int reloc; if (p->type == perc_entry_none || p->type == perc_entry_reg)
/* Non-zero if for v9 only. */ break;
int v9_p;
/* Non-zero if can be used in pc-relative contexts. */
int pcrel_p;/*FIXME:wip*/
} ops[] = {
/* hix/lox must appear before hi/lo so %hix won't be
mistaken for %hi. */
{ "hix", 3, BFD_RELOC_SPARC_HIX22, 1, 0 },
{ "lox", 3, BFD_RELOC_SPARC_LOX10, 1, 0 },
{ "hi", 2, BFD_RELOC_HI22, 0, 1 },
{ "lo", 2, BFD_RELOC_LO10, 0, 1 },
{ "pc22", 4, BFD_RELOC_SPARC_PC22, 0, 1 },
{ "pc10", 4, BFD_RELOC_SPARC_PC10, 0, 1 },
{ "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 },
{ "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 },
{ "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 },
{ "h34", 3, BFD_RELOC_SPARC_H34, 1, 0 },
{ "l34", 3, BFD_RELOC_SPARC_L44, 1, 0 },
{ "h44", 3, BFD_RELOC_SPARC_H44, 1, 0 },
{ "m44", 3, BFD_RELOC_SPARC_M44, 1, 0 },
{ "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 },
{ "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 },
{ "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 },
{ "tgd_hi22", 8, BFD_RELOC_SPARC_TLS_GD_HI22, 0, 0 },
{ "tgd_lo10", 8, BFD_RELOC_SPARC_TLS_GD_LO10, 0, 0 },
{ "tldm_hi22", 9, BFD_RELOC_SPARC_TLS_LDM_HI22, 0, 0 },
{ "tldm_lo10", 9, BFD_RELOC_SPARC_TLS_LDM_LO10, 0, 0 },
{ "tldo_hix22", 10, BFD_RELOC_SPARC_TLS_LDO_HIX22, 0,
0 },
{ "tldo_lox10", 10, BFD_RELOC_SPARC_TLS_LDO_LOX10, 0,
0 },
{ "tie_hi22", 8, BFD_RELOC_SPARC_TLS_IE_HI22, 0, 0 },
{ "tie_lo10", 8, BFD_RELOC_SPARC_TLS_IE_LO10, 0, 0 },
{ "tle_hix22", 9, BFD_RELOC_SPARC_TLS_LE_HIX22, 0, 0 },
{ "tle_lox10", 9, BFD_RELOC_SPARC_TLS_LE_LOX10, 0, 0 },
{ "gdop_hix22", 10, BFD_RELOC_SPARC_GOTDATA_OP_HIX22,
0, 0 },
{ "gdop_lox10", 10, BFD_RELOC_SPARC_GOTDATA_OP_LOX10,
0, 0 },
{ NULL, 0, 0, 0, 0 }
};
const struct ops *o;
for (o = ops; o->name; o++) if (s[p->len + 1] != '(')
if (strncmp (s + 1, o->name, o->len) == 0)
break;
if (o->name == NULL)
break;
if (s[o->len + 1] != '(')
{ {
as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name); as_bad (_("Illegal operands: %%%s requires arguments in ()"), p->name);
return special_case; return special_case;
} }
op_arg = o->name; op_arg = p->name;
the_insn.reloc = o->reloc; the_insn.reloc = p->pop->reloc;
s += o->len + 2; s += p->len + 2;
v9_arg_p = o->v9_p; v9_arg_p = p->pop->flags & F_POP_V9;
} }
/* Note that if the get_expression() fails, we will still /* Note that if the get_expression() fails, we will still