The table is sorted. Suitable for searching by a binary search. */
-static const struct pd_reg pre_defined_registers[] =
+static const struct pd_reg reg_names[] =
{
/* VSX accumulators. */
{ "a0", 0, PPC_OPERAND_ACC },
{ "xer", 1, PPC_OPERAND_SPR }
};
+#define REG_NAME_CNT (sizeof (reg_names) / sizeof (struct pd_reg))
-#define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
+static const struct pd_reg cr_names[] =
+{
+ { "cr0", 0, PPC_OPERAND_CR_REG },
+ { "cr1", 1, PPC_OPERAND_CR_REG },
+ { "cr2", 2, PPC_OPERAND_CR_REG },
+ { "cr3", 3, PPC_OPERAND_CR_REG },
+ { "cr4", 4, PPC_OPERAND_CR_REG },
+ { "cr5", 5, PPC_OPERAND_CR_REG },
+ { "cr6", 6, PPC_OPERAND_CR_REG },
+ { "cr7", 7, PPC_OPERAND_CR_REG },
+ { "eq", 2, PPC_OPERAND_CR_BIT },
+ { "gt", 1, PPC_OPERAND_CR_BIT },
+ { "lt", 0, PPC_OPERAND_CR_BIT },
+ { "so", 3, PPC_OPERAND_CR_BIT },
+ { "un", 3, PPC_OPERAND_CR_BIT }
+};
+#define CR_NAME_CNT (sizeof (cr_names) / sizeof (struct pd_reg))
/* Given NAME, find the register number associated with that name, return
the integer value associated with the given name or -1 on failure. */
return NULL;
}
-/*
- * Summary of register_name.
- *
- * in: Input_line_pointer points to 1st char of operand.
- *
- * out: A expressionS.
- * The operand may have been a register: in this case, X_op == O_register,
- * X_add_number is set to the register number, and truth is returned.
- * Input_line_pointer->(next non-blank) char after operand, or is in its
- * original state.
- */
+\f
+static bool cr_operand;
-static bool
-register_name (expressionS *expressionP)
+int
+ppc_parse_name (const char *name, expressionS *exp)
{
+ symbolS *symbol;
const struct pd_reg *reg;
- char *name;
- char *start;
- char c;
/* Find the spelling of the operand. */
- start = name = input_line_pointer;
if (name[0] == '%' && ISALPHA (name[1]))
- name = ++input_line_pointer;
-
- else if (!reg_names_p || !ISALPHA (name[0]))
- return false;
-
- c = get_symbol_name (&name);
- reg = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
-
- /* Put back the delimiting char. */
- *input_line_pointer = c;
+ ++name;
+ else if (!cr_operand && (!reg_names_p || !ISALPHA (name[0])))
+ return 0;
/* Look to see if it's in the register table. */
+ if (cr_operand)
+ reg = reg_name_search (cr_names, CR_NAME_CNT, name);
+ else
+ reg = reg_name_search (reg_names, REG_NAME_CNT, name);
if (reg != NULL)
{
- expressionP->X_op = O_register;
- expressionP->X_add_number = reg->value;
- expressionP->X_md = reg->flags;
+ exp->X_op = O_register;
+ exp->X_add_number = reg->value;
+ exp->X_md = reg->flags;
- /* Make the rest nice. */
- expressionP->X_add_symbol = NULL;
- expressionP->X_op_symbol = NULL;
- return true;
- }
+ if (! cr_operand)
+ {
+ /* Make the rest nice. */
+ exp->X_add_symbol = NULL;
+ exp->X_op_symbol = NULL;
+ }
- /* Reset the line as if we had not done anything. */
- input_line_pointer = start;
- return false;
-}
-\f
-/* This function is called for each symbol seen in an expression. It
- handles the special parsing which PowerPC assemblers are supposed
- to use for condition codes. */
+ return 1;
+ }
-/* Whether to do the special parsing. */
-static bool cr_operand;
+ /* Look to see if it's a macro. */
+ symbol = symbol_find_or_make (name);
+ if (symbol != NULL)
+ {
+ expressionS symbol_exp = *symbol_get_value_expression (symbol);
-/* Names to recognize in a condition code. This table is sorted. */
-static const struct pd_reg cr_names[] =
-{
- { "cr0", 0, PPC_OPERAND_CR_REG },
- { "cr1", 1, PPC_OPERAND_CR_REG },
- { "cr2", 2, PPC_OPERAND_CR_REG },
- { "cr3", 3, PPC_OPERAND_CR_REG },
- { "cr4", 4, PPC_OPERAND_CR_REG },
- { "cr5", 5, PPC_OPERAND_CR_REG },
- { "cr6", 6, PPC_OPERAND_CR_REG },
- { "cr7", 7, PPC_OPERAND_CR_REG },
- { "eq", 2, PPC_OPERAND_CR_BIT },
- { "gt", 1, PPC_OPERAND_CR_BIT },
- { "lt", 0, PPC_OPERAND_CR_BIT },
- { "so", 3, PPC_OPERAND_CR_BIT },
- { "un", 3, PPC_OPERAND_CR_BIT }
-};
+ if ((symbol_exp.X_op == O_register)
+ || (symbol_exp.X_op == O_constant))
+ {
+ *exp = symbol_exp;
+ return 1;
+ }
+ }
-/* Parsing function. This returns non-zero if it recognized an
- expression. */
+ return 0;
+}
-int
-ppc_parse_name (const char *name, expressionS *exp)
+void
+ppc_operand (expressionS *exp)
{
- const struct pd_reg *reg;
-
- if (! cr_operand)
- return 0;
-
- if (*name == '%')
- ++name;
- reg = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0],
- name);
- if (reg == NULL)
- return 0;
-
- exp->X_op = O_register;
- exp->X_add_number = reg->value;
- exp->X_md = reg->flags;
+ char endc;
+ char *name = input_line_pointer;
- return 1;
+ endc = get_symbol_name (&name);
+ if (!ppc_parse_name (name, exp))
+ restore_line_pointer (endc);
}
/* Propagate X_md and check register expressions. This is to support
#endif
/* This routine is called for each instruction to be assembled. */
-
void
md_assemble (char *str)
{
/* Gather the operand. */
hold = input_line_pointer;
input_line_pointer = str;
-
- if ((reg_names_p
- && (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
- || ((operand->flags & PPC_OPERAND_CR_REG) != 0)))
- || !register_name (&ex))
- {
- char save_lex = lex_type['%'];
-
- if (((operand->flags & PPC_OPERAND_CR_REG) != 0)
- || (operand->flags & PPC_OPERAND_CR_BIT) != 0)
- {
- cr_operand = true;
- lex_type['%'] |= LEX_BEGIN_NAME;
- }
- expression (&ex);
- cr_operand = false;
- lex_type['%'] = save_lex;
- }
-
+ memset (&ex, 0, sizeof (expressionS));
+ if (operand->flags & (PPC_OPERAND_CR_BIT | PPC_OPERAND_CR_REG))
+ cr_operand = true;
+ expression (&ex);
+ cr_operand = false;
str = input_line_pointer;
input_line_pointer = hold;
int
tc_ppc_regname_to_dw2regnum (char *regname)
{
- unsigned int regnum = -1;
unsigned int i;
- const char *p;
- char *q;
+ const struct pd_reg *reg;
static struct { const char *name; int dw2regnum; } regnames[] =
{
{ "sp", 1 }, { "r.sp", 1 }, { "rtoc", 2 }, { "r.toc", 2 },
if (strcmp (regnames[i].name, regname) == 0)
return regnames[i].dw2regnum;
- if (regname[0] == 'r' || regname[0] == 'f' || regname[0] == 'v')
- {
- p = regname + 1 + (regname[1] == '.');
- regnum = strtoul (p, &q, 10);
- if (p == q || *q || regnum >= 32)
- return -1;
- if (regname[0] == 'f')
- regnum += 32;
- else if (regname[0] == 'v')
- regnum += 77;
- }
- else if (regname[0] == 'c' && regname[1] == 'r')
- {
- p = regname + 2 + (regname[2] == '.');
- if (p[0] < '0' || p[0] > '7' || p[1])
- return -1;
- regnum = p[0] - '0' + 68;
- }
- return regnum;
+ if (regname[0] == '%' && ISALPHA (regname[1]))
+ ++regname;
+
+ reg = reg_name_search (reg_names, REG_NAME_CNT, regname);
+ if (reg == NULL)
+ reg = reg_name_search (cr_names, CR_NAME_CNT, regname);
+
+ if (reg != NULL)
+ return reg->value;
+
+ return -1;
}