mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-25 21:41:47 +08:00
PowerPC: implement md_operand to parse register names
Allows register names to appear in symbol assignments, so for example tocp = %r2 mr %r3,tocp now assembles. * gas/config/tc-ppc.c (REG_NAME_CNT): Delete, replace uses with ARRAY_SIZE. (register_name): Rename to.. (md_operand): ..this. Only handle %reg. (cr_names): Rename to.. (cr_cond): ..this. Just keep conditions. (ppc_parse_name): Add mode param. Search both cr_cond and pre_defined_registers. Handle absolute and register symbol values here rather than in expr.c:operand(). (md_assemble): Don't special case register name matching in operands, except to set cr_operand as appropriate. * gas/config/tc-ppc.h (md_operand): Don't define. (md_parse_name, ppc_parse_name): Update. * read.c (pseudo_set): Copy over entire O_register value. * testsuite/gas/ppc/regsyms.d. * testsuite/gas/ppc/regsyms.s: New test. * testsuite/gas/ppc/ppc.exp: Run it.
This commit is contained in:
@ -785,8 +785,6 @@ static const struct pd_reg pre_defined_registers[] =
|
|||||||
{ "xer", 1, PPC_OPERAND_SPR }
|
{ "xer", 1, PPC_OPERAND_SPR }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
|
|
||||||
|
|
||||||
/* Given NAME, find the register number associated with that name, return
|
/* Given NAME, find the register number associated with that name, return
|
||||||
the integer value associated with the given name or -1 on failure. */
|
the integer value associated with the given name or -1 on failure. */
|
||||||
|
|
||||||
@ -815,76 +813,43 @@ reg_name_search (const struct pd_reg *regs, int regcount, const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Called for a non-symbol, non-number operand. Handles %reg. */
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static bool
|
void
|
||||||
register_name (expressionS *expressionP)
|
md_operand (expressionS *expressionP)
|
||||||
{
|
{
|
||||||
const struct pd_reg *reg;
|
const struct pd_reg *reg;
|
||||||
char *name;
|
char *name;
|
||||||
char *start;
|
char *start;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
/* Find the spelling of the operand. */
|
if (input_line_pointer[0] != '%' || !ISALPHA (input_line_pointer[1]))
|
||||||
start = name = input_line_pointer;
|
return;
|
||||||
if (name[0] == '%' && ISALPHA (name[1]))
|
|
||||||
name = ++input_line_pointer;
|
|
||||||
|
|
||||||
else if (!reg_names_p || !ISALPHA (name[0]))
|
start = input_line_pointer;
|
||||||
return false;
|
++input_line_pointer;
|
||||||
|
|
||||||
c = get_symbol_name (&name);
|
c = get_symbol_name (&name);
|
||||||
reg = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
|
reg = reg_name_search (pre_defined_registers,
|
||||||
|
ARRAY_SIZE (pre_defined_registers), name);
|
||||||
/* Put back the delimiting char. */
|
|
||||||
*input_line_pointer = c;
|
*input_line_pointer = c;
|
||||||
|
|
||||||
/* Look to see if it's in the register table. */
|
|
||||||
if (reg != NULL)
|
if (reg != NULL)
|
||||||
{
|
{
|
||||||
expressionP->X_op = O_register;
|
expressionP->X_op = O_register;
|
||||||
expressionP->X_add_number = reg->value;
|
expressionP->X_add_number = reg->value;
|
||||||
expressionP->X_md = reg->flags;
|
expressionP->X_md = reg->flags;
|
||||||
|
|
||||||
/* Make the rest nice. */
|
|
||||||
expressionP->X_add_symbol = NULL;
|
|
||||||
expressionP->X_op_symbol = NULL;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* Reset the line as if we had not done anything. */
|
|
||||||
input_line_pointer = start;
|
input_line_pointer = start;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
|
|
||||||
/* Whether to do the special parsing. */
|
/* Whether to do the special parsing. */
|
||||||
static bool cr_operand;
|
static bool cr_operand;
|
||||||
|
|
||||||
/* Names to recognize in a condition code. This table is sorted. */
|
/* Extra names to recognise in a condition code. This table is sorted. */
|
||||||
static const struct pd_reg cr_names[] =
|
static const struct pd_reg cr_cond[] =
|
||||||
{
|
{
|
||||||
{ "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 },
|
{ "eq", 2, PPC_OPERAND_CR_BIT },
|
||||||
{ "gt", 1, PPC_OPERAND_CR_BIT },
|
{ "gt", 1, PPC_OPERAND_CR_BIT },
|
||||||
{ "lt", 0, PPC_OPERAND_CR_BIT },
|
{ "lt", 0, PPC_OPERAND_CR_BIT },
|
||||||
@ -892,29 +857,60 @@ static const struct pd_reg cr_names[] =
|
|||||||
{ "un", 3, PPC_OPERAND_CR_BIT }
|
{ "un", 3, PPC_OPERAND_CR_BIT }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Parsing function. This returns non-zero if it recognized an
|
/* This function is called for each symbol seen in an expression. It
|
||||||
expression. */
|
handles the special parsing which PowerPC assemblers are supposed
|
||||||
|
to use for condition codes, and recognises other registers when
|
||||||
|
-mregnames. */
|
||||||
|
|
||||||
int
|
int
|
||||||
ppc_parse_name (const char *name, expressionS *exp)
|
ppc_parse_name (const char *name, expressionS *exp, enum expr_mode mode)
|
||||||
{
|
{
|
||||||
const struct pd_reg *reg;
|
const struct pd_reg *reg = NULL;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
if (cr_operand)
|
||||||
|
reg = reg_name_search (cr_cond, ARRAY_SIZE (cr_cond), name);
|
||||||
|
if (reg == NULL && (cr_operand || reg_names_p))
|
||||||
|
reg = reg_name_search (pre_defined_registers,
|
||||||
|
ARRAY_SIZE (pre_defined_registers), name);
|
||||||
|
if (reg != NULL)
|
||||||
|
{
|
||||||
exp->X_op = O_register;
|
exp->X_op = O_register;
|
||||||
exp->X_add_number = reg->value;
|
exp->X_add_number = reg->value;
|
||||||
exp->X_md = reg->flags;
|
exp->X_md = reg->flags;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
/* The following replaces code in expr.c operand() after the
|
||||||
|
md_parse_name call. There is too much difference between targets
|
||||||
|
in the way X_md is used to move this code into expr.c. If you
|
||||||
|
do, you'll get failures on x86 due to uninitialised X_md fields,
|
||||||
|
failures on alpha and other targets due to creating register
|
||||||
|
symbols as O_constant rather than O_register, and failures on arc
|
||||||
|
and others due to expecting expr() to leave X_md alone. */
|
||||||
|
symbolS *sym = symbol_find_or_make (name);
|
||||||
|
|
||||||
|
/* If we have an absolute symbol or a reg, then we know its value
|
||||||
|
now. Copy the symbol value expression to propagate X_md. */
|
||||||
|
bool done = false;
|
||||||
|
if (mode != expr_defer
|
||||||
|
&& !S_FORCE_RELOC (sym, 0))
|
||||||
|
{
|
||||||
|
segT segment = S_GET_SEGMENT (sym);
|
||||||
|
if (segment == absolute_section || segment == reg_section)
|
||||||
|
{
|
||||||
|
resolve_symbol_value (sym);
|
||||||
|
*exp = *symbol_get_value_expression (sym);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!done)
|
||||||
|
{
|
||||||
|
exp->X_op = O_symbol;
|
||||||
|
exp->X_add_symbol = sym;
|
||||||
|
exp->X_add_number = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Propagate X_md and check register expressions. This is to support
|
/* Propagate X_md and check register expressions. This is to support
|
||||||
@ -3437,25 +3433,10 @@ md_assemble (char *str)
|
|||||||
/* Gather the operand. */
|
/* Gather the operand. */
|
||||||
hold = input_line_pointer;
|
hold = input_line_pointer;
|
||||||
input_line_pointer = str;
|
input_line_pointer = str;
|
||||||
|
cr_operand = ((operand->flags & PPC_OPERAND_CR_BIT) != 0
|
||||||
if ((reg_names_p
|
|| (operand->flags & PPC_OPERAND_CR_REG) != 0);
|
||||||
&& (((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);
|
expression (&ex);
|
||||||
cr_operand = false;
|
cr_operand = false;
|
||||||
lex_type['%'] = save_lex;
|
|
||||||
}
|
|
||||||
|
|
||||||
str = input_line_pointer;
|
str = input_line_pointer;
|
||||||
input_line_pointer = hold;
|
input_line_pointer = hold;
|
||||||
|
|
||||||
|
@ -322,14 +322,12 @@ extern void ppc_frob_label (symbolS *);
|
|||||||
/* call md_pcrel_from_section, not md_pcrel_from */
|
/* call md_pcrel_from_section, not md_pcrel_from */
|
||||||
#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX, SEC)
|
#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX, SEC)
|
||||||
|
|
||||||
#define md_parse_name(name, exp, mode, c) ppc_parse_name (name, exp)
|
#define md_parse_name(name, exp, mode, c) ppc_parse_name (name, exp, mode)
|
||||||
extern int ppc_parse_name (const char *, struct expressionS *);
|
extern int ppc_parse_name (const char *, struct expressionS *, enum expr_mode);
|
||||||
|
|
||||||
#define md_optimize_expr(left, op, right) ppc_optimize_expr (left, op, right)
|
#define md_optimize_expr(left, op, right) ppc_optimize_expr (left, op, right)
|
||||||
extern int ppc_optimize_expr (expressionS *, operatorT, expressionS *);
|
extern int ppc_optimize_expr (expressionS *, operatorT, expressionS *);
|
||||||
|
|
||||||
#define md_operand(x)
|
|
||||||
|
|
||||||
#define md_cleanup() ppc_cleanup ()
|
#define md_cleanup() ppc_cleanup ()
|
||||||
extern void ppc_cleanup (void);
|
extern void ppc_cleanup (void);
|
||||||
|
|
||||||
|
@ -3934,10 +3934,9 @@ pseudo_set (symbolS *symbolP)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
symbol_set_value_expression (symbolP, &exp);
|
||||||
S_SET_SEGMENT (symbolP, reg_section);
|
S_SET_SEGMENT (symbolP, reg_section);
|
||||||
S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
|
|
||||||
set_zero_frag (symbolP);
|
set_zero_frag (symbolP);
|
||||||
symbol_get_value_expression (symbolP)->X_op = O_register;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case O_symbol:
|
case O_symbol:
|
||||||
|
@ -36,6 +36,7 @@ run_dump_test "bcy"
|
|||||||
run_dump_test "bcaterr"
|
run_dump_test "bcaterr"
|
||||||
run_dump_test "bcat"
|
run_dump_test "bcat"
|
||||||
run_dump_test "regnames"
|
run_dump_test "regnames"
|
||||||
|
run_dump_test "regsyms"
|
||||||
run_dump_test "misalign"
|
run_dump_test "misalign"
|
||||||
run_dump_test "misalign2"
|
run_dump_test "misalign2"
|
||||||
run_dump_test "machine"
|
run_dump_test "machine"
|
||||||
|
10
gas/testsuite/gas/ppc/regsyms.d
Normal file
10
gas/testsuite/gas/ppc/regsyms.d
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#as: -mregnames
|
||||||
|
#objdump: -d
|
||||||
|
|
||||||
|
.*: file format .*
|
||||||
|
|
||||||
|
Disassembly of section \.text:
|
||||||
|
|
||||||
|
0+ <.text>:
|
||||||
|
0: (7c 43 13 78|78 13 43 7c) mr r3,r2
|
||||||
|
4: (7f c3 f3 78|78 f3 c3 7f) mr r3,r30
|
4
gas/testsuite/gas/ppc/regsyms.s
Normal file
4
gas/testsuite/gas/ppc/regsyms.s
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
tocp = %r2
|
||||||
|
mr %r3,tocp
|
||||||
|
x = r30
|
||||||
|
mr 3,x
|
Reference in New Issue
Block a user