From 3ae41265b503cc27a96180f029c531282ea94584 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Sun, 24 Jul 2022 10:01:45 +0300 Subject: [PATCH] ppc/svp64: allow predicate macro expansion --- gas/config/tc-ppc-svp64.c | 198 +++++++++++++++++++++++++++++--------- gas/config/tc-ppc.c | 15 ++- gas/config/tc-ppc.h | 3 + 3 files changed, 171 insertions(+), 45 deletions(-) diff --git a/gas/config/tc-ppc-svp64.c b/gas/config/tc-ppc-svp64.c index 0073a746c6f..4a072667d6d 100644 --- a/gas/config/tc-ppc-svp64.c +++ b/gas/config/tc-ppc-svp64.c @@ -71,6 +71,33 @@ enum svp64_type { SVP64_TYPE_BC, }; +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) { @@ -109,16 +136,10 @@ svp64_operand (expressionS *exp) *origin = '*'; } -static void -svp64_parse_name (const char *name, expressionS *exp, enum expr_mode mode) -{ - ppc_parse_name_common (name, exp, mode, svp64_regs, svp64_num_regs); -} - 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; @@ -174,7 +195,6 @@ svp64_expression (char *str, expressionS *exp) *str++ = '\0'; str_tail = str; old_sep = *str; - *str = '\0'; str = str_head; input_line_pointer = str; @@ -186,49 +206,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; @@ -240,10 +248,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 f3d3f04054d..5aa4722c9c7 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -961,8 +961,11 @@ ppc_resolve_symbol (symbolS *sym ATTRIBUTE_UNUSED, case O_vector: *seg = reg_section; break; + case O_predicate: + *seg = absolute_section; + break; default: - abort (); + abort(); } return true; @@ -1015,6 +1018,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 a1bb70bcf99..1022ab3b3eb 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 -- 2.30.2