From: Dmitry Selyutin Date: Sun, 28 May 2023 22:04:56 +0000 (+0300) Subject: ppc/svp64: support m/dm/sm modes X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4d400035ede4842b3b5297d6cbebb6e490efd2a0;p=binutils-gdb.git ppc/svp64: support m/dm/sm modes --- diff --git a/gas/config/tc-ppc-svp64.c b/gas/config/tc-ppc-svp64.c index 89d62c218a5..46887d86739 100644 --- a/gas/config/tc-ppc-svp64.c +++ b/gas/config/tc-ppc-svp64.c @@ -24,6 +24,15 @@ struct svp64_ctx { const char *name; const struct svp64_desc *desc; + unsigned int pmmode : 1; + unsigned int pmask : 3; + unsigned int smmode : 1; + unsigned int smask : 3; + unsigned int mmode : 1; + unsigned int has_pmask : 1; + unsigned int has_smask : 1; + unsigned int mask_m_specified : 1; + unsigned int subvl : 2; }; static jmp_buf svp64_exception; @@ -63,10 +72,170 @@ svp64_setup_records (void) #define SVP64_SEP '/' +struct svp64_predicate_map { + const char *str; + unsigned int len : 3; + unsigned int cr : 1; + unsigned int mask : 3; +}; +#define SVP64_PREDICATE_MAP(STR, MODE, MASK) \ + { STR, (sizeof (STR) - 1), MODE, MASK } + +static char * +svp64_decode_predicate (char *str, bool *cr, unsigned int *mask) +{ + size_t i; + static const struct svp64_predicate_map table[] = { + /* integer */ + SVP64_PREDICATE_MAP ("1<str, entry->len) != 0) + continue; + + str += entry->len; + if (! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0') + { + str -= entry->len; + continue; + } + + *mask = entry->mask; + *cr = entry->cr; + + *str++ = '\0'; + + return str; + } + + return NULL; +} + +struct svp64_decoder { + char *(*call)(char *str, struct svp64_ctx *svp64); + const char *str; + size_t len; +}; +#define SVP64_DECODER(STR, CALL) \ + { CALL, STR, (sizeof (STR) - 1) } + +static char * +svp64_decode_m (char *str, struct svp64_ctx *svp64) +{ + char *iter; + bool cr; + unsigned int pmmode; + unsigned int pmask; + + str += (sizeof ("m=") - 1); + iter = svp64_decode_predicate (str, &cr, &pmask); + if (!iter) + svp64_raise (_("unrecognized mode: `%s'"), str); + + pmmode = (cr ? 1 : 0); + svp64->pmmode = pmmode; + svp64->pmask = pmask; + svp64->smmode = pmmode; + svp64->smask = pmask; + svp64->mmode = pmmode; + svp64->mask_m_specified = 1; + + return iter; +} + +static char * +svp64_decode_dm (char *str, struct svp64_ctx *svp64) +{ + char *iter; + bool cr; + unsigned int pmmode; + unsigned int pmask; + + str += (sizeof ("dm=") - 1); + iter = svp64_decode_predicate (str, &cr, &pmask); + if (!iter) + svp64_raise (_("unrecognized mode: `%s'"), str); + + pmmode = (cr ? 1 : 0); + svp64->pmmode = pmmode; + svp64->pmask = pmask; + svp64->mmode = pmmode; + svp64->has_pmask = 1; + + return iter; +} + +static char * +svp64_decode_sm (char *str, struct svp64_ctx *svp64) +{ + char *iter; + bool cr; + unsigned int smmode; + unsigned int smask; + + str += (sizeof ("sm=") - 1); + iter = svp64_decode_predicate (str, &cr, &smask); + if (!iter) + svp64_raise (_("unrecognized mode: `%s'"), str); + + smmode = (cr ? 1 : 0); + svp64->smmode = smmode; + svp64->smask = smask; + svp64->mmode = smmode; + svp64->has_smask = 1; + + return iter; +} + +static char * +svp64_decode_mode (char *str, struct svp64_ctx *svp64) +{ + size_t i; + static const struct svp64_decoder table[] = { + SVP64_DECODER ("m=" , svp64_decode_m), + SVP64_DECODER ("dm=" , svp64_decode_dm), + SVP64_DECODER ("sm=" , svp64_decode_sm), + }; + + for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i) + { + const struct svp64_decoder *entry = &table[i]; + + if (strncmp (str, entry->str, entry->len) == 0) + return entry->call (str, svp64); + } + + return NULL; +} + static void svp64_decode (char *str, struct svp64_ctx *svp64) { char *opc; + char *iter; const struct svp64_record *record; str += (sizeof ("sv.") - 1); @@ -86,6 +255,9 @@ svp64_decode (char *str, struct svp64_ctx *svp64) record = (const void *)((unsigned char *)svp64->desc - offsetof (struct svp64_record, desc)); svp64->name = record->name; + + for (; (iter = svp64_decode_mode (str, svp64)) != NULL; str = iter) + ; } static void