From: Dmitry Selyutin Date: Sun, 28 May 2023 22:04:56 +0000 (+0300) Subject: ppc/svp64: allow predicate macro expansion X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=31737c73c9c926abd27e3dc01f806036f3a457fd;p=binutils-gdb.git ppc/svp64: allow predicate macro expansion --- diff --git a/gas/config/tc-ppc-svp64.c b/gas/config/tc-ppc-svp64.c index 84512ff5932..8f0cd06b67d 100644 --- a/gas/config/tc-ppc-svp64.c +++ b/gas/config/tc-ppc-svp64.c @@ -61,6 +61,33 @@ struct svp64_ctx { #define SVP64_RC1_ACTIVE (1U << 3U) #define SVP64_RC1_INVERT (SVP64_RC1_ACTIVE | (1U << 4U)) +enum svp64_predicate { + /* Integer */ + SVP64_PREDICATE_1BIT_R3, + SVP64_PREDICATE_R3, + SVP64_PREDICATE_R3_INV, + SVP64_PREDICATE_R10, + SVP64_PREDICATE_R10_INV, + SVP64_PREDICATE_R30, + SVP64_PREDICATE_R30_INV, + /* CR */ + SVP64_PREDICATE_LT, + SVP64_PREDICATE_NL, + SVP64_PREDICATE_GE = SVP64_PREDICATE_NL, + SVP64_PREDICATE_GT, + SVP64_PREDICATE_NG, + SVP64_PREDICATE_LE = SVP64_PREDICATE_NG, + SVP64_PREDICATE_EQ, + SVP64_PREDICATE_NE, + SVP64_PREDICATE_SO, + SVP64_PREDICATE_UN = SVP64_PREDICATE_SO, + SVP64_PREDICATE_NS, + SVP64_PREDICATE_NU = SVP64_PREDICATE_NS, + /* RC1 */ + SVP64_PREDICATE_RC1, + SVP64_PREDICATE_RC1_INV, +}; + static void svp64_operand (expressionS *exp) { @@ -99,16 +126,33 @@ svp64_operand (expressionS *exp) *origin = '*'; } -static void -svp64_parse_name (const char *name, expressionS *exp, enum expr_mode mode) +static inline void +svp64_optimize_cr_cond (expressionS *exp) { - ppc_parse_name_common (name, exp, mode, svp64_regs, svp64_num_regs); + size_t i; + static const enum svp64_predicate table[] = { + SVP64_PREDICATE_LT, + SVP64_PREDICATE_GT, + SVP64_PREDICATE_EQ, + SVP64_PREDICATE_SO, + }; + + for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i) + { + if (exp->X_add_number == table[i]) + { + exp->X_op = O_register; + exp->X_add_number = (offsetT)i; + exp->X_md = PPC_OPERAND_CR_BIT; + return; + } + } } static bool svp64_special_expr (expressionS *exp) { - return (exp->X_op == O_vector); + return ((exp->X_op == O_vector) || (exp->X_op == O_predicate)); } static jmp_buf svp64_exception; @@ -164,7 +208,6 @@ svp64_expression (char *str, expressionS *exp) *str++ = '\0'; str_tail = str; old_sep = *str; - *str = '\0'; str = str_head; input_line_pointer = str; @@ -177,49 +220,37 @@ svp64_expression (char *str, expressionS *exp) return ((exp->X_op == O_absent) ? str_head : str_tail); } -struct svp64_predicate_map { +struct svp64_predicate_cr_map { const char *str; unsigned int len : 3; - unsigned int cr : 1; - unsigned int mask : 3 + 2; /* 3-bit plus RC1 */ + unsigned int id : 5; }; -#define SVP64_PREDICATE_MAP(STR, MODE, MASK) \ - { STR, (sizeof (STR) - 1), MODE, MASK } +#define SVP64_PREDICATE_CR_MAP(STR, ID) \ + { STR, (sizeof (STR) - 1), ID } -static char * -svp64_decode_predicate (char *str, bool *cr, unsigned int *mask) +static bool +svp64_parse_predicate_cr (const char *name, expressionS *exp) { size_t i; - static const struct svp64_predicate_map table[] = { - /* integer */ - SVP64_PREDICATE_MAP ("1<str, entry->len) != 0) continue; @@ -231,10 +262,112 @@ svp64_decode_predicate (char *str, bool *cr, unsigned int *mask) continue; } - *mask = entry->mask; - *cr = entry->cr; + exp->X_op = O_predicate; + exp->X_add_number = entry->id; + + return true; + } + + return false; +} + +static bool +svp64_parse_predicate_RC1 (const char *name, expressionS *exp) +{ + if (strcmp (name, "RC1") == 0) + { + exp->X_op = O_predicate; + exp->X_add_number = SVP64_PREDICATE_RC1; + return true; + } + else + return false; +} + +static void +svp64_parse_name (const char *name, expressionS *exp, enum expr_mode mode) +{ + exp->X_op = O_absent; + exp->X_op_symbol = NULL; + exp->X_add_symbol = NULL; + + if ((svp64_parse_predicate_cr (name, exp) + || svp64_parse_predicate_RC1 (name, exp)) == 0) + ppc_parse_name_common (name, exp, mode, svp64_regs, svp64_num_regs); +} + +static char * +svp64_decode_predicate (char *str, bool *cr, unsigned int *mask) +{ + char *origin; + expressionS exp; + + origin = str; + str = svp64_expression (str, &exp); + if (str != origin) + { + expressionS *sym_exp = NULL; + static const struct { + unsigned int cr : 1; + unsigned int mask : 3 + 2; /* 3-bit plus RC1 */ + } table[] = { + /* SVP64_PREDICATE_1BIT_R3 */ {0, 1}, + /* SVP64_PREDICATE_R3 */ {0, 2}, + /* SVP64_PREDICATE_R3_INV */ {0, 3}, + /* SVP64_PREDICATE_R10 */ {0, 4}, + /* SVP64_PREDICATE_R10_INV */ {0, 5}, + /* SVP64_PREDICATE_R30 */ {0, 6}, + /* SVP64_PREDICATE_R30_INV */ {0, 7}, + /* SVP64_PREDICATE_LT */ {1, 0}, + /* SVP64_PREDICATE_NL */ {1, 1}, + /* SVP64_PREDICATE_GT */ {1, 2}, + /* SVP64_PREDICATE_NG */ {1, 3}, + /* SVP64_PREDICATE_EQ */ {1, 4}, + /* SVP64_PREDICATE_NE */ {1, 5}, + /* SVP64_PREDICATE_SO */ {1, 6}, + /* SVP64_PREDICATE_NS */ {1, 7}, + /* {SVP64_PREDICATE_RC1*/ {0, SVP64_RC1_ACTIVE}, + /* SVP64_PREDICATE_RC1_INV */ {0, SVP64_RC1_INVERT}, + }; + enum svp64_predicate predicate; + + if (exp.X_add_symbol) + sym_exp = symbol_get_value_expression (exp.X_add_symbol); + + if ((exp.X_op == O_register) && + ((exp.X_add_number == 3) + || (exp.X_add_number == 10) + || (exp.X_add_number == 30))) + { + exp.X_op = O_predicate; + if (exp.X_add_number == 3) + exp.X_add_number = SVP64_PREDICATE_R3; + else if (exp.X_add_number == 10) + exp.X_add_number = SVP64_PREDICATE_R10; + else if (exp.X_add_number == 30) + exp.X_add_number = SVP64_PREDICATE_R30; + } + else if ((exp.X_op == O_bit_not) && (sym_exp != NULL)) + { + if (sym_exp->X_op == O_register) + { + if (sym_exp->X_add_number == 3) + exp.X_add_number = SVP64_PREDICATE_R3_INV; + else if (sym_exp->X_add_number == 10) + exp.X_add_number = SVP64_PREDICATE_R10_INV; + else if (sym_exp->X_add_number == 30) + exp.X_add_number = SVP64_PREDICATE_R30_INV; + } + else if ((sym_exp->X_op == O_predicate) + && (sym_exp->X_add_number == SVP64_PREDICATE_RC1)) + exp.X_add_number = SVP64_PREDICATE_RC1_INV; + } + else if (exp.X_op != O_predicate) + return NULL; - *str++ = '\0'; + predicate = (enum svp64_predicate)exp.X_add_number; + *cr = (table[predicate].cr ? true : false); + *mask = table[predicate].mask; return str; } diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index a0da2f6db39..06aff47890d 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -971,6 +971,9 @@ ppc_resolve_symbol (symbolS *sym ATTRIBUTE_UNUSED, case O_vector: *seg = reg_section; break; + case O_predicate: + *seg = absolute_section; + break; default: abort (); } @@ -980,7 +983,6 @@ ppc_resolve_symbol (symbolS *sym ATTRIBUTE_UNUSED, /* Propagate X_md and check register expressions. This is to support condition codes like 4*cr5+eq. */ - int ppc_optimize_expr (expressionS *left, operatorT op, expressionS *right) { @@ -1003,13 +1005,17 @@ ppc_optimize_expr (expressionS *left, operatorT op, expressionS *right) /* Accept the above plus , and plus the above. */ if (op == O_add - && left->X_op == O_register - && right->X_op == O_register + && ((left->X_op == O_register) || (left->X_op == O_predicate)) + && ((right->X_op == O_register) || (right->X_op == O_predicate)) && ((right->X_md == PPC_OPERAND_CR_BIT && left->X_md == (PPC_OPERAND_CR_REG | PPC_OPERAND_CR_BIT)) || (right->X_md == (PPC_OPERAND_CR_REG | PPC_OPERAND_CR_BIT) - && left->X_md == PPC_OPERAND_CR_BIT))) + && (left->X_md == PPC_OPERAND_CR_BIT || left->X_op == O_predicate)))) { + if (left->X_op == O_predicate) + svp64_optimize_cr_cond (left); + if (right->X_op == O_predicate) + svp64_optimize_cr_cond (right); left->X_md = PPC_OPERAND_CR_BIT; right->X_op = O_constant; return 0; @@ -1025,6 +1031,16 @@ ppc_optimize_expr (expressionS *left, operatorT op, expressionS *right) { if (op == O_add && left->X_op == O_constant) left->X_md = right->X_md; + else if ((ppc_cpu & PPC_OPCODE_SVP64) + && (op == O_left_shift) + && (left->X_op == O_constant) + && (left->X_add_number == 1) + && (right->X_add_number == 3)) /* 1<X_op = O_predicate; + left->X_add_number = SVP64_PREDICATE_1BIT_R3; + return 1; + } else as_warn (_("invalid register expression")); } diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index fce6c98e0ba..45878020914 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -368,6 +368,9 @@ extern int tc_ppc_regname_to_dw2regnum (char *); */ #define O_vector O_md1 +/* Operand is a predicate to s/dm/sm/ff/pr modes. */ +#define O_predicate O_md2 + extern bool ppc_resolve_symbol (symbolS *sym, valueT *val, segT *seg); #define md_resolve_symbol ppc_resolve_symbol