struct svp64_ctx {
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;
#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<<r3", 0, 1),
+ SVP64_PREDICATE_MAP ("r3" , 0, 2),
+ SVP64_PREDICATE_MAP ("~r3" , 0, 3),
+ SVP64_PREDICATE_MAP ("r10" , 0, 4),
+ SVP64_PREDICATE_MAP ("~r10" , 0, 5),
+ SVP64_PREDICATE_MAP ("r30" , 0, 6),
+ SVP64_PREDICATE_MAP ("~r30" , 0, 7),
+ /* CR */
+ SVP64_PREDICATE_MAP ("lt" , 1, 0),
+ SVP64_PREDICATE_MAP ("nl" , 1, 1),
+ SVP64_PREDICATE_MAP ("ge" , 1, 1), /* same value as nl */
+ SVP64_PREDICATE_MAP ("gt" , 1, 2),
+ SVP64_PREDICATE_MAP ("ng" , 1, 3),
+ SVP64_PREDICATE_MAP ("le" , 1, 3), /* same value as ng */
+ SVP64_PREDICATE_MAP ("eq" , 1, 4),
+ SVP64_PREDICATE_MAP ("ne" , 1, 5),
+ SVP64_PREDICATE_MAP ("so" , 1, 6),
+ SVP64_PREDICATE_MAP ("un" , 1, 6), /* same value as so */
+ SVP64_PREDICATE_MAP ("ns" , 1, 7),
+ SVP64_PREDICATE_MAP ("nu" , 1, 7), /* same value as ns */
+ };
+
+ for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i)
+ {
+ const struct svp64_predicate_map *entry = &table[i];
+
+ if (strncmp (str, entry->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;
str += (sizeof ("sv.") - 1);
if (! ISALPHA (*str))
if (*str != '\0')
*str++ = '\0';
+ for (; (iter = svp64_decode_mode (str, svp64)) != NULL; str = iter)
+ ;
+
svp64->desc = (const struct svp64_desc *) str_hash_find (svp64_hash, opc);
if (!svp64->desc)
svp64_raise (_("unrecognized opcode: `%s'"), str);