* [PATCH 0/1] ppc: support register names in macros @ 2022-07-12 13:50 Dmitry Selyutin 2022-07-12 13:50 ` [PATCH 1/1] " Dmitry Selyutin 2022-07-12 21:22 ` [PATCH v2 0/1] " Dmitry Selyutin 0 siblings, 2 replies; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-12 13:50 UTC (permalink / raw) To: binutils; +Cc: Alan Modra, Luke Leighton, Jan Beulich, Dmitry Selyutin This patch is a follow-up of discussion: https://sourceware.org/pipermail/binutils/2022-July/121719.html Form now on, PPC assembly becomes capable of compiling such code: .set VREG, %r0 .set REG, VREG extsw REG, 2 extsw %r1, 1 The custom register_name() code path, as well as checks for CRs, are deprecated; from now on, we use md_operand() routine everywhere. Whilst we're here, let's also reuse register lookup for CFI. Dmitry Selyutin (1): ppc: support register names in macros gas/config/tc-ppc.c | 206 +++++++++++++++++--------------------------- gas/config/tc-ppc.h | 9 +- 2 files changed, 86 insertions(+), 129 deletions(-) -- 2.37.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 1/1] ppc: support register names in macros 2022-07-12 13:50 [PATCH 0/1] ppc: support register names in macros Dmitry Selyutin @ 2022-07-12 13:50 ` Dmitry Selyutin 2022-07-12 14:13 ` Dmitry Selyutin 2022-07-12 14:18 ` lkcl 2022-07-12 21:22 ` [PATCH v2 0/1] " Dmitry Selyutin 1 sibling, 2 replies; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-12 13:50 UTC (permalink / raw) To: binutils; +Cc: Alan Modra, Luke Leighton, Jan Beulich, Dmitry Selyutin This patch is a follow-up of discussion: https://sourceware.org/pipermail/binutils/2022-July/121719.html Form now on, PPC assembly becomes capable of compiling such code: .set VREG, %r0 .set REG, VREG extsw REG, 2 extsw %r1, 1 The custom register_name() code path, as well as checks for CRs, are deprecated; from now on, we use md_operand() routine everywhere. Whilst we're here, let's also reuse register lookup for CFI. --- gas/config/tc-ppc.c | 206 +++++++++++++++++--------------------------- gas/config/tc-ppc.h | 9 +- 2 files changed, 86 insertions(+), 129 deletions(-) diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index ac61cd8f12..0b814c4873 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -317,7 +317,7 @@ struct pd_reg 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 }, @@ -784,8 +784,25 @@ static const struct pd_reg pre_defined_registers[] = { "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. */ @@ -815,106 +832,68 @@ reg_name_search (const struct pd_reg *regs, int regcount, const char *name) 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 @@ -3276,7 +3255,6 @@ parse_tls_arg (char **str, const expressionS *exp, struct ppc_fixup *tls_fix) #endif /* This routine is called for each instruction to be assembled. */ - void md_assemble (char *str) { @@ -3439,25 +3417,11 @@ 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; @@ -7736,10 +7700,8 @@ ppc_cfi_frame_initial_instructions (void) 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 }, @@ -7752,23 +7714,15 @@ tc_ppc_regname_to_dw2regnum (char *regname) 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; } diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index ed06a29638..da3c427c4a 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -322,14 +322,17 @@ extern void ppc_frob_label (symbolS *); /* call md_pcrel_from_section, not md_pcrel_from */ #define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX, SEC) +#define LEX_PCT (LEX_BEGIN_NAME) + +extern int ppc_parse_name (const char *name, struct expressionS *exp); #define md_parse_name(name, exp, mode, c) ppc_parse_name (name, exp) -extern int ppc_parse_name (const char *, struct expressionS *); + +extern void ppc_operand (expressionS *exp); +#define md_operand ppc_operand #define md_optimize_expr(left, op, right) ppc_optimize_expr (left, op, right) extern int ppc_optimize_expr (expressionS *, operatorT, expressionS *); -#define md_operand(x) - #define md_cleanup() ppc_cleanup () extern void ppc_cleanup (void); -- 2.37.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/1] ppc: support register names in macros 2022-07-12 13:50 ` [PATCH 1/1] " Dmitry Selyutin @ 2022-07-12 14:13 ` Dmitry Selyutin 2022-07-12 14:18 ` lkcl 1 sibling, 0 replies; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-12 14:13 UTC (permalink / raw) To: Binutils; +Cc: Alan Modra, Luke Leighton, Jan Beulich On Tue, Jul 12, 2022 at 4:51 PM Dmitry Selyutin <ghostmansd@gmail.com> wrote: > @@ -7752,23 +7714,15 @@ tc_ppc_regname_to_dw2regnum (char *regname) > 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; > } I'm by no means a CFI expert, so I'm not sure whether we should be able to accept all registers here. Judging from the original (overly simplified) code, we should only consider a register with one of these flags: PPC_OPERAND_GPR PPC_OPERAND_FPR PPC_OPERAND_VR PPC_OPERAND_CR_REG I'm inclined to add this check for reg->flags. Any objections? -- Best regards, Dmitry Selyutin ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/1] ppc: support register names in macros 2022-07-12 13:50 ` [PATCH 1/1] " Dmitry Selyutin 2022-07-12 14:13 ` Dmitry Selyutin @ 2022-07-12 14:18 ` lkcl 2022-07-12 14:24 ` Dmitry Selyutin 1 sibling, 1 reply; 19+ messages in thread From: lkcl @ 2022-07-12 14:18 UTC (permalink / raw) To: Dmitry Selyutin; +Cc: lkcl via Binutils, Alan Modra, Jan Beulich On Tue, Jul 12, 2022 at 2:51 PM Dmitry Selyutin <ghostmansd@gmail.com> wrote: > + { "eq", 2, PPC_OPERAND_CR_BIT }, ne? > + { "gt", 1, PPC_OPERAND_CR_BIT }, ge? > + { "lt", 0, PPC_OPERAND_CR_BIT }, le? > + { "so", 3, PPC_OPERAND_CR_BIT }, > + { "un", 3, PPC_OPERAND_CR_BIT } > +}; > +#define CR_NAME_CNT (sizeof (cr_names) / sizeof (struct pd_reg)) ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/1] ppc: support register names in macros 2022-07-12 14:18 ` lkcl @ 2022-07-12 14:24 ` Dmitry Selyutin 0 siblings, 0 replies; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-12 14:24 UTC (permalink / raw) To: lkcl; +Cc: lkcl via Binutils, Alan Modra, Jan Beulich On Tue, Jul 12, 2022 at 5:18 PM lkcl <luke.leighton@gmail.com> wrote: > > On Tue, Jul 12, 2022 at 2:51 PM Dmitry Selyutin <ghostmansd@gmail.com> wrote: > > + { "eq", 2, PPC_OPERAND_CR_BIT }, > ne? > > + { "gt", 1, PPC_OPERAND_CR_BIT }, > ge? > > + { "lt", 0, PPC_OPERAND_CR_BIT }, > le? - { "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 } This code simply was moved. So it either has been wrong all this time, or it is correct. :-) -- Best regards, Dmitry Selyutin ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2 0/1] ppc: support register names in macros 2022-07-12 13:50 [PATCH 0/1] ppc: support register names in macros Dmitry Selyutin 2022-07-12 13:50 ` [PATCH 1/1] " Dmitry Selyutin @ 2022-07-12 21:22 ` Dmitry Selyutin 2022-07-12 21:22 ` [PATCH v2 1/1] " Dmitry Selyutin 1 sibling, 1 reply; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-12 21:22 UTC (permalink / raw) To: binutils; +Cc: Alan Modra, Luke Leighton, Jan Beulich, Dmitry Selyutin This patch is a follow-up of discussion: https://sourceware.org/pipermail/binutils/2022-July/121719.html Form now on, PPC assembly becomes capable of compiling such code: .set VREG, %r0 .set REG, VREG extsw REG, 2 extsw %r1, 1 The custom register_name() code path, as well as checks for CRs, are deprecated; from now on, we use md_operand() routine everywhere. Whilst we're here, let's also reuse register lookup for CFI. Changes since v1: - Dropped incorrect and redundant logic regarding symbol lookup. - Added restoring of input line pointer on failure. - Refactored the patch so that it shows less changes. Dmitry Selyutin (1): ppc: support register names in macros gas/config/tc-ppc.c | 232 +++++++++++++++++--------------------------- gas/config/tc-ppc.h | 9 +- 2 files changed, 96 insertions(+), 145 deletions(-) -- 2.37.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2 1/1] ppc: support register names in macros 2022-07-12 21:22 ` [PATCH v2 0/1] " Dmitry Selyutin @ 2022-07-12 21:22 ` Dmitry Selyutin 2022-07-12 21:29 ` [PATCH v3 0/1] " Dmitry Selyutin 0 siblings, 1 reply; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-12 21:22 UTC (permalink / raw) To: binutils; +Cc: Alan Modra, Luke Leighton, Jan Beulich, Dmitry Selyutin This patch is a follow-up of discussion: https://sourceware.org/pipermail/binutils/2022-July/121719.html Form now on, PPC assembly becomes capable of compiling such code: .set VREG, %r0 .set REG, VREG extsw REG, 2 extsw %r1, 1 The custom register_name() code path, as well as checks for CRs, are deprecated; from now on, we use md_operand() routine everywhere. Whilst we're here, let's also reuse register lookup for CFI. --- gas/config/tc-ppc.c | 232 +++++++++++++++++--------------------------- gas/config/tc-ppc.h | 9 +- 2 files changed, 96 insertions(+), 145 deletions(-) diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 5015777d60..283cefc3a4 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -317,7 +317,7 @@ struct pd_reg 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 }, @@ -784,95 +784,7 @@ static const struct pd_reg pre_defined_registers[] = { "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 - the integer value associated with the given name or -1 on failure. */ - -static const struct pd_reg * -reg_name_search (const struct pd_reg *regs, int regcount, const char *name) -{ - int middle, low, high; - int cmp; - - low = 0; - high = regcount - 1; - - do - { - middle = (low + high) / 2; - cmp = strcasecmp (name, regs[middle].name); - if (cmp < 0) - high = middle - 1; - else if (cmp > 0) - low = middle + 1; - else - return ®s[middle]; - } - while (low <= high); - - 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. - */ - -static bool -register_name (expressionS *expressionP) -{ - 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; - - /* Look to see if it's in the register table. */ - if (reg != NULL) - { - expressionP->X_op = O_register; - expressionP->X_add_number = reg->value; - expressionP->X_md = reg->flags; - - /* Make the rest nice. */ - expressionP->X_add_symbol = NULL; - expressionP->X_op_symbol = NULL; - return true; - } - - /* 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. */ - -/* Whether to do the special parsing. */ -static bool cr_operand; +#define REG_NAME_CNT (sizeof (reg_names) / sizeof (struct pd_reg)) /* Names to recognize in a condition code. This table is sorted. */ static const struct pd_reg cr_names[] = @@ -891,6 +803,10 @@ static const struct pd_reg cr_names[] = { "so", 3, PPC_OPERAND_CR_BIT }, { "un", 3, PPC_OPERAND_CR_BIT } }; +#define CR_NAME_CNT (sizeof (cr_names) / sizeof (struct pd_reg)) + +/* Whether to do the special parsing. */ +static bool cr_operand; /* Parsing function. This returns non-zero if it recognized an expression. */ @@ -900,23 +816,79 @@ ppc_parse_name (const char *name, expressionS *exp) { const struct pd_reg *reg; - if (! cr_operand) - return 0; - - if (*name == '%') + if (name[0] == '%' && ISALPHA (name[1])) ++name; - reg = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0], - name); - if (reg == NULL) + else if (!cr_operand && (!reg_names_p || !ISALPHA (name[0]))) return 0; - exp->X_op = O_register; - exp->X_add_number = reg->value; - exp->X_md = reg->flags; + 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) + { + exp->X_op = O_register; + exp->X_add_number = reg->value; + exp->X_md = reg->flags; - return 1; + if (! cr_operand) + { + /* Make the rest nice. */ + exp->X_add_symbol = NULL; + exp->X_op_symbol = NULL; + } + + return 1; + } + + return 0; +} + +void +ppc_operand (expressionS *exp) +{ + char endc; + char *name; + char *origin = input_line_pointer; + + endc = get_symbol_name (&name); + if (! ppc_parse_name (name, exp)) + { + restore_line_pointer (endc); + input_line_pointer = origin; + } } +/* Given NAME, find the register number associated with that name, return + the integer value associated with the given name or -1 on failure. */ + +static const struct pd_reg * +reg_name_search (const struct pd_reg *regs, int regcount, const char *name) +{ + int middle, low, high; + int cmp; + + low = 0; + high = regcount - 1; + + do + { + middle = (low + high) / 2; + cmp = strcasecmp (name, regs[middle].name); + if (cmp < 0) + high = middle - 1; + else if (cmp > 0) + low = middle + 1; + else + return ®s[middle]; + } + while (low <= high); + + return NULL; +} + +\f + /* Propagate X_md and check register expressions. This is to support condition codes like 4*cr5+eq. */ @@ -3437,25 +3409,11 @@ 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; @@ -7734,10 +7692,8 @@ ppc_cfi_frame_initial_instructions (void) 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 }, @@ -7750,23 +7706,15 @@ tc_ppc_regname_to_dw2regnum (char *regname) 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; } diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index ed06a29638..da3c427c4a 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -322,14 +322,17 @@ extern void ppc_frob_label (symbolS *); /* call md_pcrel_from_section, not md_pcrel_from */ #define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX, SEC) +#define LEX_PCT (LEX_BEGIN_NAME) + +extern int ppc_parse_name (const char *name, struct expressionS *exp); #define md_parse_name(name, exp, mode, c) ppc_parse_name (name, exp) -extern int ppc_parse_name (const char *, struct expressionS *); + +extern void ppc_operand (expressionS *exp); +#define md_operand ppc_operand #define md_optimize_expr(left, op, right) ppc_optimize_expr (left, op, right) extern int ppc_optimize_expr (expressionS *, operatorT, expressionS *); -#define md_operand(x) - #define md_cleanup() ppc_cleanup () extern void ppc_cleanup (void); -- 2.37.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 0/1] ppc: support register names in macros 2022-07-12 21:22 ` [PATCH v2 1/1] " Dmitry Selyutin @ 2022-07-12 21:29 ` Dmitry Selyutin 2022-07-12 21:29 ` [PATCH v3 1/1] " Dmitry Selyutin 0 siblings, 1 reply; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-12 21:29 UTC (permalink / raw) To: binutils; +Cc: Alan Modra, Luke Leighton, Jan Beulich, Dmitry Selyutin This patch is a follow-up of discussion: https://sourceware.org/pipermail/binutils/2022-July/121719.html Form now on, PPC assembly becomes capable of compiling such code: .set VREG, %r0 .set REG, VREG extsw REG, 2 extsw %r1, 1 The custom register_name() code path, as well as checks for CRs, are deprecated; from now on, we use md_operand() routine everywhere. Whilst we're here, let's also reuse register lookup for CFI. Changes since v2: - Moved reg_name_search to the correct place. Changes since v1: - Dropped incorrect and redundant logic regarding symbol lookup. - Added restoring of input line pointer on failure. - Refactored the patch so that it shows less changes. Dmitry Selyutin (1): ppc: support register names in macros gas/config/tc-ppc.c | 204 +++++++++++++++++--------------------------- gas/config/tc-ppc.h | 9 +- 2 files changed, 82 insertions(+), 131 deletions(-) -- 2.37.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3 1/1] ppc: support register names in macros 2022-07-12 21:29 ` [PATCH v3 0/1] " Dmitry Selyutin @ 2022-07-12 21:29 ` Dmitry Selyutin 2022-07-13 15:34 ` Alan Modra 0 siblings, 1 reply; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-12 21:29 UTC (permalink / raw) To: binutils; +Cc: Alan Modra, Luke Leighton, Jan Beulich, Dmitry Selyutin This patch is a follow-up of discussion: https://sourceware.org/pipermail/binutils/2022-July/121719.html Form now on, PPC assembly becomes capable of compiling such code: .set VREG, %r0 .set REG, VREG extsw REG, 2 extsw %r1, 1 The custom register_name() code path, as well as checks for CRs, are deprecated; from now on, we use md_operand() routine everywhere. Whilst we're here, let's also reuse register lookup for CFI. --- gas/config/tc-ppc.c | 204 +++++++++++++++++--------------------------- gas/config/tc-ppc.h | 9 +- 2 files changed, 82 insertions(+), 131 deletions(-) diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 5015777d60..181b1edc4d 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -317,7 +317,7 @@ struct pd_reg 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 }, @@ -784,8 +784,26 @@ static const struct pd_reg pre_defined_registers[] = { "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)) +/* 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 } +}; +#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. */ @@ -815,83 +833,9 @@ reg_name_search (const struct pd_reg *regs, int regcount, const char *name) 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. - */ - -static bool -register_name (expressionS *expressionP) -{ - 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; - - /* Look to see if it's in the register table. */ - if (reg != NULL) - { - expressionP->X_op = O_register; - expressionP->X_add_number = reg->value; - expressionP->X_md = reg->flags; - - /* Make the rest nice. */ - expressionP->X_add_symbol = NULL; - expressionP->X_op_symbol = NULL; - return true; - } - - /* 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. */ - /* Whether to do the special parsing. */ static bool cr_operand; -/* 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 } -}; - /* Parsing function. This returns non-zero if it recognized an expression. */ @@ -900,23 +844,51 @@ ppc_parse_name (const char *name, expressionS *exp) { const struct pd_reg *reg; - if (! cr_operand) - return 0; - - if (*name == '%') + if (name[0] == '%' && ISALPHA (name[1])) ++name; - reg = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0], - name); - if (reg == NULL) + else if (!cr_operand && (!reg_names_p || !ISALPHA (name[0]))) return 0; - exp->X_op = O_register; - exp->X_add_number = reg->value; - exp->X_md = reg->flags; + 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) + { + exp->X_op = O_register; + exp->X_add_number = reg->value; + exp->X_md = reg->flags; + + if (! cr_operand) + { + /* Make the rest nice. */ + exp->X_add_symbol = NULL; + exp->X_op_symbol = NULL; + } - return 1; + return 1; + } + + return 0; } +void +ppc_operand (expressionS *exp) +{ + char endc; + char *name; + char *origin = input_line_pointer; + + endc = get_symbol_name (&name); + if (! ppc_parse_name (name, exp)) + { + restore_line_pointer (endc); + input_line_pointer = origin; + } +} + +\f + /* Propagate X_md and check register expressions. This is to support condition codes like 4*cr5+eq. */ @@ -3437,25 +3409,11 @@ 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; @@ -7734,10 +7692,8 @@ ppc_cfi_frame_initial_instructions (void) 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 }, @@ -7750,23 +7706,15 @@ tc_ppc_regname_to_dw2regnum (char *regname) 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; } diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index ed06a29638..da3c427c4a 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -322,14 +322,17 @@ extern void ppc_frob_label (symbolS *); /* call md_pcrel_from_section, not md_pcrel_from */ #define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section(FIX, SEC) +#define LEX_PCT (LEX_BEGIN_NAME) + +extern int ppc_parse_name (const char *name, struct expressionS *exp); #define md_parse_name(name, exp, mode, c) ppc_parse_name (name, exp) -extern int ppc_parse_name (const char *, struct expressionS *); + +extern void ppc_operand (expressionS *exp); +#define md_operand ppc_operand #define md_optimize_expr(left, op, right) ppc_optimize_expr (left, op, right) extern int ppc_optimize_expr (expressionS *, operatorT, expressionS *); -#define md_operand(x) - #define md_cleanup() ppc_cleanup () extern void ppc_cleanup (void); -- 2.37.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 1/1] ppc: support register names in macros 2022-07-12 21:29 ` [PATCH v3 1/1] " Dmitry Selyutin @ 2022-07-13 15:34 ` Alan Modra 2022-07-14 6:03 ` PowerPC: implement md_operand to parse register names Alan Modra 2022-07-14 6:04 ` [PATCH v3 1/1] ppc: support register names in macros Dmitry Selyutin 0 siblings, 2 replies; 19+ messages in thread From: Alan Modra @ 2022-07-13 15:34 UTC (permalink / raw) To: Dmitry Selyutin; +Cc: binutils, Luke Leighton, Jan Beulich On Wed, Jul 13, 2022 at 12:29:59AM +0300, Dmitry Selyutin wrote: > +#define LEX_PCT (LEX_BEGIN_NAME) > + This would allow '%' to start symbols and labels, and I think that is a bad idea. I've also been working on a patch, wasting a lot of time trying to change expr.c:operand in a way that allows the powerpc register type checks in X_md to work. ie. .set a,%f4 .set b,%cr3 .set c,%r31 addi a,b,c ought to warn about invalid registers. In the end I gave up and just moved some code from operand() to ppc_parse_name(). I'll commit the following tomorrow assuming overnight checks pass. * 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. (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. diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 5015777d600..05d8ee19be7 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -785,8 +785,6 @@ static const struct pd_reg pre_defined_registers[] = { "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 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; } -/* - * 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. - */ +/* Called for a non-symbol, non-number operand. Handles %reg. */ -static bool -register_name (expressionS *expressionP) +void +md_operand (expressionS *expressionP) { 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; + if (input_line_pointer[0] != '%' || !ISALPHA (input_line_pointer[1])) + return; - else if (!reg_names_p || !ISALPHA (name[0])) - return false; + start = input_line_pointer; + ++input_line_pointer; c = get_symbol_name (&name); - reg = reg_name_search (pre_defined_registers, REG_NAME_CNT, name); - - /* Put back the delimiting char. */ + reg = reg_name_search (pre_defined_registers, + ARRAY_SIZE (pre_defined_registers), name); *input_line_pointer = c; - /* Look to see if it's in the register table. */ if (reg != NULL) { expressionP->X_op = O_register; expressionP->X_add_number = reg->value; expressionP->X_md = reg->flags; - - /* Make the rest nice. */ - expressionP->X_add_symbol = NULL; - expressionP->X_op_symbol = NULL; - return true; } - - /* Reset the line as if we had not done anything. */ - input_line_pointer = start; - return false; + else + input_line_pointer = start; } -\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. */ /* Whether to do the special parsing. */ static bool cr_operand; -/* Names to recognize in a condition code. This table is sorted. */ -static const struct pd_reg cr_names[] = +/* Extra names to recognise in a condition code. This table is sorted. */ +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 }, { "gt", 1, 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 } }; -/* Parsing function. This returns non-zero if it recognized an - expression. */ +/* 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, and recognises other registers when + -mregnames. */ 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 (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_add_number = reg->value; + exp->X_md = reg->flags; + return true; + } - if (*name == '%') - ++name; - reg = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0], - name); - if (reg == NULL) - return 0; + /* 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); - exp->X_op = O_register; - exp->X_add_number = reg->value; - exp->X_md = reg->flags; + /* 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 1; + return true; } /* Propagate X_md and check register expressions. This is to support @@ -3437,25 +3433,10 @@ 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; - } - + cr_operand = ((operand->flags & PPC_OPERAND_CR_BIT) != 0 + || (operand->flags & PPC_OPERAND_CR_REG) != 0); + expression (&ex); + cr_operand = false; str = input_line_pointer; input_line_pointer = hold; diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index ed06a296382..480c952be45 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -322,14 +322,12 @@ extern void ppc_frob_label (symbolS *); /* call md_pcrel_from_section, not md_pcrel_from */ #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) -extern int ppc_parse_name (const char *, struct expressionS *); +#define md_parse_name(name, exp, mode, c) ppc_parse_name (name, exp, mode) +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) extern int ppc_optimize_expr (expressionS *, operatorT, expressionS *); -#define md_operand(x) - #define md_cleanup() ppc_cleanup () extern void ppc_cleanup (void); diff --git a/gas/read.c b/gas/read.c index 6f3a51df761..559fd05a8db 100644 --- a/gas/read.c +++ b/gas/read.c @@ -3934,10 +3934,9 @@ pseudo_set (symbolS *symbolP) return; } #endif + symbol_set_value_expression (symbolP, &exp); S_SET_SEGMENT (symbolP, reg_section); - S_SET_VALUE (symbolP, (valueT) exp.X_add_number); set_zero_frag (symbolP); - symbol_get_value_expression (symbolP)->X_op = O_register; break; case O_symbol: diff --git a/gas/testsuite/gas/ppc/ppc.exp b/gas/testsuite/gas/ppc/ppc.exp index a2e23a2c6af..9844ce7e4a1 100644 --- a/gas/testsuite/gas/ppc/ppc.exp +++ b/gas/testsuite/gas/ppc/ppc.exp @@ -36,6 +36,7 @@ run_dump_test "bcy" run_dump_test "bcaterr" run_dump_test "bcat" run_dump_test "regnames" +run_dump_test "regsyms" run_dump_test "misalign" run_dump_test "misalign2" run_dump_test "machine" diff --git a/gas/testsuite/gas/ppc/regsyms.d b/gas/testsuite/gas/ppc/regsyms.d new file mode 100644 index 00000000000..7586b0df4ca --- /dev/null +++ b/gas/testsuite/gas/ppc/regsyms.d @@ -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 diff --git a/gas/testsuite/gas/ppc/regsyms.s b/gas/testsuite/gas/ppc/regsyms.s new file mode 100644 index 00000000000..6dc3ddc070b --- /dev/null +++ b/gas/testsuite/gas/ppc/regsyms.s @@ -0,0 +1,4 @@ + tocp = %r2 + mr %r3,tocp + x = r30 + mr 3,x -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: PowerPC: implement md_operand to parse register names 2022-07-13 15:34 ` Alan Modra @ 2022-07-14 6:03 ` Alan Modra 2022-07-14 6:04 ` [PATCH v3 1/1] ppc: support register names in macros Dmitry Selyutin 1 sibling, 0 replies; 19+ messages in thread From: Alan Modra @ 2022-07-14 6:03 UTC (permalink / raw) To: Dmitry Selyutin; +Cc: binutils, Luke Leighton, Jan Beulich I meant to make this change before committing, to let compilers know the code on the false branch of md_parse_name is dead. * config/tc-ppc.c (ppc_parse_name): Return void. * config/tc-ppc.h (md_parse_name): Always true. (ppc_parse_name): Update prototype. diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 05d8ee19be7..452fab1cbfc 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -862,7 +862,7 @@ static const struct pd_reg cr_cond[] = to use for condition codes, and recognises other registers when -mregnames. */ -int +void ppc_parse_name (const char *name, expressionS *exp, enum expr_mode mode) { const struct pd_reg *reg = NULL; @@ -877,7 +877,7 @@ ppc_parse_name (const char *name, expressionS *exp, enum expr_mode mode) exp->X_op = O_register; exp->X_add_number = reg->value; exp->X_md = reg->flags; - return true; + return; } /* The following replaces code in expr.c operand() after the @@ -909,8 +909,6 @@ ppc_parse_name (const char *name, expressionS *exp, enum expr_mode mode) exp->X_add_symbol = sym; exp->X_add_number = 0; } - - return true; } /* Propagate X_md and check register expressions. This is to support diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index 480c952be45..de9522d4bf6 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -322,8 +322,9 @@ extern void ppc_frob_label (symbolS *); /* call md_pcrel_from_section, not md_pcrel_from */ #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, mode) -extern int ppc_parse_name (const char *, struct expressionS *, enum expr_mode); +#define md_parse_name(name, exp, mode, c) \ + (ppc_parse_name (name, exp, mode), true) +extern void ppc_parse_name (const char *, struct expressionS *, enum expr_mode); #define md_optimize_expr(left, op, right) ppc_optimize_expr (left, op, right) extern int ppc_optimize_expr (expressionS *, operatorT, expressionS *); -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3 1/1] ppc: support register names in macros 2022-07-13 15:34 ` Alan Modra 2022-07-14 6:03 ` PowerPC: implement md_operand to parse register names Alan Modra @ 2022-07-14 6:04 ` Dmitry Selyutin 2022-07-14 6:05 ` [PATCH] ppc: use reg_name_search for CFI register lookup Dmitry Selyutin 1 sibling, 1 reply; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-14 6:04 UTC (permalink / raw) To: Alan Modra; +Cc: Binutils, Luke Leighton, Jan Beulich On Wed, Jul 13, 2022 at 6:34 PM Alan Modra <amodra@gmail.com> wrote: > diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c > index 5015777d600..05d8ee19be7 100644 > --- a/gas/config/tc-ppc.c > +++ b/gas/config/tc-ppc.c Whilst we're here, I suggest taking this opportunity to re-use some bits for CFI, which invented a custom register parsing. :-) -- Best regards, Dmitry Selyutin ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH] ppc: use reg_name_search for CFI register lookup 2022-07-14 6:04 ` [PATCH v3 1/1] ppc: support register names in macros Dmitry Selyutin @ 2022-07-14 6:05 ` Dmitry Selyutin 2022-07-14 7:25 ` Alan Modra 0 siblings, 1 reply; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-14 6:05 UTC (permalink / raw) To: binutils; +Cc: Alan Modra, Luke Leighton, Jan Beulich, Dmitry Selyutin --- gas/config/tc-ppc.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 05d8ee19be..765eb3fa2f 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -7715,10 +7715,8 @@ ppc_cfi_frame_initial_instructions (void) 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 }, @@ -7731,23 +7729,18 @@ tc_ppc_regname_to_dw2regnum (char *regname) 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 (pre_defined_registers, + ARRAY_SIZE (pre_defined_registers), regname); + + if ((reg != NULL) && + (((reg->flags & PPC_OPERAND_GPR) == PPC_OPERAND_GPR) || + ((reg->flags & PPC_OPERAND_FPR) == PPC_OPERAND_FPR) || + ((reg->flags & PPC_OPERAND_VR) == PPC_OPERAND_VR) || + ((reg->flags & PPC_OPERAND_CR_REG) == PPC_OPERAND_CR_REG))) + return reg->value; + + return -1; } -- 2.37.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] ppc: use reg_name_search for CFI register lookup 2022-07-14 6:05 ` [PATCH] ppc: use reg_name_search for CFI register lookup Dmitry Selyutin @ 2022-07-14 7:25 ` Alan Modra 2022-07-14 8:21 ` [PATCH v2] " Dmitry Selyutin 2022-07-14 8:23 ` [PATCH] " Dmitry Selyutin 0 siblings, 2 replies; 19+ messages in thread From: Alan Modra @ 2022-07-14 7:25 UTC (permalink / raw) To: Dmitry Selyutin; +Cc: binutils, Luke Leighton, Jan Beulich No, that's completely broken. The numbers we want to return from tc_ppc_regname_to_dw2regnum are not those in reg->value. -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2] ppc: use reg_name_search for CFI register lookup 2022-07-14 7:25 ` Alan Modra @ 2022-07-14 8:21 ` Dmitry Selyutin 2022-07-14 23:01 ` Alan Modra 2022-07-14 8:23 ` [PATCH] " Dmitry Selyutin 1 sibling, 1 reply; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-14 8:21 UTC (permalink / raw) To: binutils; +Cc: Alan Modra, Luke Leighton, Jan Beulich, Dmitry Selyutin --- gas/config/tc-ppc.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 452fab1cbf..c6715535c7 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -7713,10 +7713,8 @@ ppc_cfi_frame_initial_instructions (void) 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 }, @@ -7729,23 +7727,22 @@ tc_ppc_regname_to_dw2regnum (char *regname) 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 (pre_defined_registers, + ARRAY_SIZE (pre_defined_registers), regname); + if (reg == NULL) + return -1; + + if ((reg->flags & PPC_OPERAND_GPR) == PPC_OPERAND_GPR) + return reg->value; + else if ((reg->flags & PPC_OPERAND_FPR) == PPC_OPERAND_FPR) + return (reg->value + 32); + else if ((reg->flags & PPC_OPERAND_VR) == PPC_OPERAND_VR) + return (reg->value + 77); + else if ((reg->flags & PPC_OPERAND_CR_REG) == PPC_OPERAND_CR_REG) + return (reg->value + 68); + else + return -1; } -- 2.37.0 ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2] ppc: use reg_name_search for CFI register lookup 2022-07-14 8:21 ` [PATCH v2] " Dmitry Selyutin @ 2022-07-14 23:01 ` Alan Modra 0 siblings, 0 replies; 19+ messages in thread From: Alan Modra @ 2022-07-14 23:01 UTC (permalink / raw) To: Dmitry Selyutin; +Cc: binutils, Luke Leighton, Jan Beulich On Thu, Jul 14, 2022 at 11:21:12AM +0300, Dmitry Selyutin wrote: > --- > gas/config/tc-ppc.c | 41 +++++++++++++++++++---------------------- > 1 file changed, 19 insertions(+), 22 deletions(-) > > diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c > index 452fab1cbf..c6715535c7 100644 > --- a/gas/config/tc-ppc.c > +++ b/gas/config/tc-ppc.c > @@ -7713,10 +7713,8 @@ ppc_cfi_frame_initial_instructions (void) > 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 }, > @@ -7729,23 +7727,22 @@ tc_ppc_regname_to_dw2regnum (char *regname) > 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; No need for the above, any '%' is trimmed off and regname is guaranteed to be a name by the caller of tc_regname_to_dw2regnum. > + reg = reg_name_search (pre_defined_registers, > + ARRAY_SIZE (pre_defined_registers), regname); Doing the reg_name_search before the odd ones in regnames[] would be better, wouldn't it? And you can delete the first row of regnames[]. OK with those changes. > + if (reg == NULL) > + return -1; > + > + if ((reg->flags & PPC_OPERAND_GPR) == PPC_OPERAND_GPR) > + return reg->value; > + else if ((reg->flags & PPC_OPERAND_FPR) == PPC_OPERAND_FPR) > + return (reg->value + 32); > + else if ((reg->flags & PPC_OPERAND_VR) == PPC_OPERAND_VR) > + return (reg->value + 77); > + else if ((reg->flags & PPC_OPERAND_CR_REG) == PPC_OPERAND_CR_REG) > + return (reg->value + 68); > + else > + return -1; > } > -- > 2.37.0 -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] ppc: use reg_name_search for CFI register lookup 2022-07-14 7:25 ` Alan Modra 2022-07-14 8:21 ` [PATCH v2] " Dmitry Selyutin @ 2022-07-14 8:23 ` Dmitry Selyutin 2022-07-14 8:25 ` Dmitry Selyutin 1 sibling, 1 reply; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-14 8:23 UTC (permalink / raw) To: Alan Modra; +Cc: Binutils, Luke Leighton, Jan Beulich On Thu, Jul 14, 2022 at 10:25 AM Alan Modra <amodra@gmail.com> wrote: > > No, that's completely broken. The numbers we want to return from > tc_ppc_regname_to_dw2regnum are not those in reg->value. Yeah sorry I totally missed that the results are tuned. Updated. -- Best regards, Dmitry Selyutin ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] ppc: use reg_name_search for CFI register lookup 2022-07-14 8:23 ` [PATCH] " Dmitry Selyutin @ 2022-07-14 8:25 ` Dmitry Selyutin 2022-07-14 23:02 ` Alan Modra 0 siblings, 1 reply; 19+ messages in thread From: Dmitry Selyutin @ 2022-07-14 8:25 UTC (permalink / raw) To: Alan Modra; +Cc: Binutils, Luke Leighton, Jan Beulich On Thu, Jul 14, 2022 at 11:23 AM Dmitry Selyutin <ghostmansd@gmail.com> wrote: > Yeah sorry I totally missed that the results are tuned. Updated. Hm. Perhaps we need some test covering it? Say some as/objdump combination. It's a bit strange that cfi-ppc-1.d hasn't caught it. -- Best regards, Dmitry Selyutin ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] ppc: use reg_name_search for CFI register lookup 2022-07-14 8:25 ` Dmitry Selyutin @ 2022-07-14 23:02 ` Alan Modra 0 siblings, 0 replies; 19+ messages in thread From: Alan Modra @ 2022-07-14 23:02 UTC (permalink / raw) To: Dmitry Selyutin; +Cc: Binutils, Luke Leighton, Jan Beulich On Thu, Jul 14, 2022 at 11:25:43AM +0300, Dmitry Selyutin wrote: > On Thu, Jul 14, 2022 at 11:23 AM Dmitry Selyutin <ghostmansd@gmail.com> wrote: > > Yeah sorry I totally missed that the results are tuned. Updated. > > Hm. Perhaps we need some test covering it? Say some as/objdump > combination. It's a bit strange that cfi-ppc-1.d hasn't caught it. Yes, the test isn't that good, only checking cfi for gprs. -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2022-07-14 23:02 UTC | newest] Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-07-12 13:50 [PATCH 0/1] ppc: support register names in macros Dmitry Selyutin 2022-07-12 13:50 ` [PATCH 1/1] " Dmitry Selyutin 2022-07-12 14:13 ` Dmitry Selyutin 2022-07-12 14:18 ` lkcl 2022-07-12 14:24 ` Dmitry Selyutin 2022-07-12 21:22 ` [PATCH v2 0/1] " Dmitry Selyutin 2022-07-12 21:22 ` [PATCH v2 1/1] " Dmitry Selyutin 2022-07-12 21:29 ` [PATCH v3 0/1] " Dmitry Selyutin 2022-07-12 21:29 ` [PATCH v3 1/1] " Dmitry Selyutin 2022-07-13 15:34 ` Alan Modra 2022-07-14 6:03 ` PowerPC: implement md_operand to parse register names Alan Modra 2022-07-14 6:04 ` [PATCH v3 1/1] ppc: support register names in macros Dmitry Selyutin 2022-07-14 6:05 ` [PATCH] ppc: use reg_name_search for CFI register lookup Dmitry Selyutin 2022-07-14 7:25 ` Alan Modra 2022-07-14 8:21 ` [PATCH v2] " Dmitry Selyutin 2022-07-14 23:01 ` Alan Modra 2022-07-14 8:23 ` [PATCH] " Dmitry Selyutin 2022-07-14 8:25 ` Dmitry Selyutin 2022-07-14 23:02 ` Alan Modra
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).