#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)
{
*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;
*str++ = '\0';
str_tail = str;
old_sep = *str;
- *str = '\0';
str = str_head;
input_line_pointer = str;
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<<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 */
- /* RC1 */
- SVP64_PREDICATE_MAP ("RC1" , 0, SVP64_RC1_ACTIVE),
- SVP64_PREDICATE_MAP ("~RC1" , 0, SVP64_RC1_INVERT),
+ const char *str = name;
+ static const struct svp64_predicate_cr_map table[] = {
+ SVP64_PREDICATE_CR_MAP ("lt", SVP64_PREDICATE_LT),
+ SVP64_PREDICATE_CR_MAP ("nl", SVP64_PREDICATE_NL),
+ SVP64_PREDICATE_CR_MAP ("ge", SVP64_PREDICATE_GE),
+ SVP64_PREDICATE_CR_MAP ("gt", SVP64_PREDICATE_GT),
+ SVP64_PREDICATE_CR_MAP ("ng", SVP64_PREDICATE_NG),
+ SVP64_PREDICATE_CR_MAP ("le", SVP64_PREDICATE_LE),
+ SVP64_PREDICATE_CR_MAP ("eq", SVP64_PREDICATE_EQ),
+ SVP64_PREDICATE_CR_MAP ("ne", SVP64_PREDICATE_NE),
+ SVP64_PREDICATE_CR_MAP ("so", SVP64_PREDICATE_SO),
+ SVP64_PREDICATE_CR_MAP ("un", SVP64_PREDICATE_UN),
+ SVP64_PREDICATE_CR_MAP ("ns", SVP64_PREDICATE_NS),
+ SVP64_PREDICATE_CR_MAP ("nu", SVP64_PREDICATE_NU),
};
for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i)
{
- const struct svp64_predicate_map *entry = &table[i];
+ const struct svp64_predicate_cr_map *entry = &table[i];
if (strncmp (str, entry->str, entry->len) != 0)
continue;
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;
}