Rework the R_NEG support on both gas and ld for the PowerPC AIX targets, in order...
[binutils-gdb.git] / gas / config / xtensa-relax.c
index f8ec7ad6b4f2df844c76d4674976a60ea9f73dc6..267d436461a260d11ec2d90f1032b633f747e80f 100644 (file)
@@ -1,5 +1,5 @@
 /* Table of relaxations for Xtensa assembly.
-   Copyright 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2003-2021 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    when the first and second operands are not the same as specified
    by the "| %at!=%as" precondition clause.
    {"l32i %at,%as,%imm | %at!=%as",
-   "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l32i %at,%at,0"}
-
-   There is special case for loop instructions here, but because we do
-   not currently have the ability to represent the difference of two
-   symbols, the conversion requires special code in the assembler to
-   write the operands of the addi/addmi pair representing the
-   difference of the old and new loop end label.  */
+   "LITERAL %imm; l32r %at,%LITERAL; add %at,%at,%as; l32i %at,%at,0"}  */
 
 #include "as.h"
 #include "xtensa-isa.h"
@@ -247,7 +241,7 @@ struct string_pattern_pair_struct
      addi.n a4, 0x1010
      => addi a4, 0x1010
      => addmi a4, 0x1010
-     => addmi a4, 0x1000, addi a4, 0x10.  
+     => addmi a4, 0x1000, addi a4, 0x10.
 
    See the comments in xg_assembly_relax for some important details
    regarding how these chains must be built.  */
@@ -306,44 +300,83 @@ static string_pattern_pair widen_spec_list[] =
   {"l32i %at,%as,%imm | %at!=%as ? IsaUseConst16",
    "const16 %at,HI16U(%imm); const16 %at,LOW16U(%imm); add %at,%at,%as; l32i %at,%at,0"},
 
-  /* This is only PART of the loop instruction.  In addition,
-     hardcoded into its use is a modification of the final operand in
-     the instruction in bytes 9 and 12.  */
-  {"loop %as,%label | %as!=1 ? IsaUseLoops",
+  /* Widening loops with literals.  */
+  {"loop %as,%label | %as!=1 ? IsaUseLoops ? IsaUseL32R",
+   "loop %as,%LABEL;"
+   "rsr.lend    %as;"          /* LEND */
+   "wsr.lbeg    %as;"          /* LBEG */
+   "LITERAL     %label;"
+   "l32r        %as, %LITERAL;"
+   "nop;"
+   "wsr.lend    %as;"
+   "isync;"
+   "rsr.lcount    %as;"                /* LCOUNT */
+   "addi    %as, %as, 1;"
+   "LABEL"},
+  {"loopgtz %as,%label | %as!=1 ? IsaUseLoops ? IsaUseL32R",
+   "beqz    %as,%label;"
+   "bltz    %as,%label;"
+   "loopgtz %as,%LABEL;"
+   "rsr.lend    %as;"          /* LEND */
+   "wsr.lbeg    %as;"          /* LBEG */
+   "LITERAL     %label;"
+   "l32r        %as, %LITERAL;"
+   "nop;"
+   "wsr.lend    %as;"
+   "isync;"
+   "rsr.lcount    %as;"                /* LCOUNT */
+   "addi    %as, %as, 1;"
+   "LABEL"},
+  {"loopnez %as,%label | %as!=1 ? IsaUseLoops ? IsaUseL32R",
+   "beqz     %as,%label;"
+   "loopnez %as,%LABEL;"
+   "rsr.lend    %as;"          /* LEND */
+   "wsr.lbeg    %as;"          /* LBEG */
+   "LITERAL     %label;"
+   "l32r        %as, %LITERAL;"
+   "nop;"
+   "wsr.lend    %as;"
+   "isync;"
+   "rsr.lcount    %as;"                /* LCOUNT */
+   "addi    %as, %as, 1;"
+   "LABEL"},
+
+  /* Widening loops with const16.  */
+  {"loop %as,%label | %as!=1 ? IsaUseLoops ? IsaUseConst16",
    "loop %as,%LABEL;"
    "rsr.lend    %as;"          /* LEND */
    "wsr.lbeg    %as;"          /* LBEG */
-   "addi    %as, %as, 0;"      /* lo8(%label-%LABEL1) */
-   "addmi   %as, %as, 0;"      /* mid8(%label-%LABEL1) */
+   "const16     %as,HI16U(%label);"
+   "const16     %as,LOW16U(%label);"
    "wsr.lend    %as;"
    "isync;"
    "rsr.lcount    %as;"                /* LCOUNT */
-   "addi    %as, %as, 1;"      /* density -> addi.n %as, %as, 1 */
+   "addi    %as, %as, 1;"
    "LABEL"},
-  {"loopgtz %as,%label | %as!=1 ? IsaUseLoops",
+  {"loopgtz %as,%label | %as!=1 ? IsaUseLoops ? IsaUseConst16",
    "beqz    %as,%label;"
    "bltz    %as,%label;"
    "loopgtz %as,%LABEL;"
    "rsr.lend    %as;"          /* LEND */
    "wsr.lbeg    %as;"          /* LBEG */
-   "addi    %as, %as, 0;"      /* lo8(%label-%LABEL1) */
-   "addmi   %as, %as, 0;"      /* mid8(%label-%LABEL1) */
+   "const16     %as,HI16U(%label);"
+   "const16     %as,LOW16U(%label);"
    "wsr.lend    %as;"
    "isync;"
    "rsr.lcount    %as;"                /* LCOUNT */
-   "addi    %as, %as, 1;"      /* density -> addi.n %as, %as, 1 */
+   "addi    %as, %as, 1;"
    "LABEL"},
-  {"loopnez %as,%label | %as!=1 ? IsaUseLoops",
+  {"loopnez %as,%label | %as!=1 ? IsaUseLoops ? IsaUseConst16",
    "beqz     %as,%label;"
    "loopnez %as,%LABEL;"
    "rsr.lend    %as;"          /* LEND */
    "wsr.lbeg    %as;"          /* LBEG */
-   "addi    %as, %as, 0;"      /* lo8(%label-%LABEL1) */
-   "addmi   %as, %as, 0;"      /* mid8(%label-%LABEL1) */
+   "const16     %as,HI16U(%label);"
+   "const16     %as,LOW16U(%label);"
    "wsr.lend    %as;"
    "isync;"
    "rsr.lcount    %as;"                /* LCOUNT */
-   "addi    %as, %as, 1;"      /* density -> addi.n %as, %as, 1 */
+   "addi    %as, %as, 1;"
    "LABEL"},
 
   /* Relaxing to wide branches.  Order is important here.  With wide
@@ -351,7 +384,7 @@ static string_pattern_pair widen_spec_list[] =
      out-of-range branch.  Put the wide branch relaxations first in the
      table since they are more efficient than the branch-around
      relaxations.  */
-  
+
   {"beqz %as,%label ? IsaUseWideBranches", "WIDE.beqz %as,%label"},
   {"bnez %as,%label ? IsaUseWideBranches", "WIDE.bnez %as,%label"},
   {"bgez %as,%label ? IsaUseWideBranches", "WIDE.bgez %as,%label"},
@@ -376,7 +409,7 @@ static string_pattern_pair widen_spec_list[] =
   {"bnall %as,%at,%label ? IsaUseWideBranches", "WIDE.bnall %as,%at,%label"},
   {"bbc %as,%at,%label ? IsaUseWideBranches", "WIDE.bbc %as,%at,%label"},
   {"bbs %as,%at,%label ? IsaUseWideBranches", "WIDE.bbs %as,%at,%label"},
-  
+
   /* Widening branch comparisons eq/ne to zero.  Prefer relaxing to narrow
      branches if the density option is available.  */
   {"beqz %as,%label ? IsaUseDensityInstruction", "bnez.n %as,%LABEL;j %label;LABEL"},
@@ -512,7 +545,7 @@ string_pattern_pair simplify_spec_list[] =
 \f
 /* Externally visible functions.  */
 
-extern bfd_boolean xg_has_userdef_op_fn (OpType);
+extern bool xg_has_userdef_op_fn (OpType);
 extern long xg_apply_userdef_op_fn (OpType, long);
 
 
@@ -522,7 +555,7 @@ append_transition (TransitionTable *tt,
                   TransitionRule *t,
                   transition_cmp_fn cmp)
 {
-  TransitionList *tl = (TransitionList *) xmalloc (sizeof (TransitionList));
+  TransitionList *tl = XNEW (TransitionList);
   TransitionList *prev;
   TransitionList **t_p;
   gas_assert (tt != NULL);
@@ -554,8 +587,7 @@ append_transition (TransitionTable *tt,
 static void
 append_condition (TransitionRule *tr, Precondition *cond)
 {
-  PreconditionList *pl =
-    (PreconditionList *) xmalloc (sizeof (PreconditionList));
+  PreconditionList *pl = XNEW (PreconditionList);
   PreconditionList *prev = tr->conditions;
   PreconditionList *nxt;
 
@@ -582,7 +614,7 @@ append_value_condition (TransitionRule *tr,
                        unsigned op1,
                        unsigned op2)
 {
-  Precondition *cond = (Precondition *) xmalloc (sizeof (Precondition));
+  Precondition *cond = XNEW (Precondition);
 
   cond->cmp = cmp;
   cond->op_num = op1;
@@ -598,7 +630,7 @@ append_constant_value_condition (TransitionRule *tr,
                                 unsigned op1,
                                 unsigned cnst)
 {
-  Precondition *cond = (Precondition *) xmalloc (sizeof (Precondition));
+  Precondition *cond = XNEW (Precondition);
 
   cond->cmp = cmp;
   cond->op_num = op1;
@@ -654,7 +686,7 @@ append_op (BuildInstr *bi, BuildOp *b_op)
 static void
 append_literal_op (BuildInstr *bi, unsigned op1, unsigned src_op)
 {
-  BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
+  BuildOp *b_op = XNEW (BuildOp);
 
   b_op->op_num = op1;
   b_op->typ = OP_LITERAL;
@@ -667,7 +699,7 @@ append_literal_op (BuildInstr *bi, unsigned op1, unsigned src_op)
 static void
 append_label_op (BuildInstr *bi, unsigned op1)
 {
-  BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
+  BuildOp *b_op = XNEW (BuildOp);
 
   b_op->op_num = op1;
   b_op->typ = OP_LABEL;
@@ -680,7 +712,7 @@ append_label_op (BuildInstr *bi, unsigned op1)
 static void
 append_constant_op (BuildInstr *bi, unsigned op1, unsigned cnst)
 {
-  BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
+  BuildOp *b_op = XNEW (BuildOp);
 
   b_op->op_num = op1;
   b_op->typ = OP_CONSTANT;
@@ -693,7 +725,7 @@ append_constant_op (BuildInstr *bi, unsigned op1, unsigned cnst)
 static void
 append_field_op (BuildInstr *bi, unsigned op1, unsigned src_op)
 {
-  BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
+  BuildOp *b_op = XNEW (BuildOp);
 
   b_op->op_num = op1;
   b_op->typ = OP_OPERAND;
@@ -711,7 +743,7 @@ append_user_fn_field_op (BuildInstr *bi,
                         OpType typ,
                         unsigned src_op)
 {
-  BuildOp *b_op = (BuildOp *) xmalloc (sizeof (BuildOp));
+  BuildOp *b_op = XNEW (BuildOp);
 
   b_op->op_num = op1;
   b_op->typ = typ;
@@ -766,7 +798,7 @@ operand_function_HI16U (long a)
 }
 
 
-bfd_boolean
+bool
 xg_has_userdef_op_fn (OpType op)
 {
   switch (op)
@@ -776,11 +808,11 @@ xg_has_userdef_op_fn (OpType op)
     case OP_OPERAND_HI24S:
     case OP_OPERAND_LOW16U:
     case OP_OPERAND_HI16U:
-      return TRUE;
+      return true;
     default:
       break;
     }
-  return FALSE;
+  return false;
 }
 
 
@@ -802,7 +834,7 @@ xg_apply_userdef_op_fn (OpType op, long a)
     default:
       break;
     }
-  return FALSE;
+  return false;
 }
 
 
@@ -819,10 +851,8 @@ enter_opname_n (const char *name, int len)
          && strncmp (op->opname, name, len) == 0)
        return op->opname;
     }
-  op = (opname_e *) xmalloc (sizeof (opname_e));
-  op->opname = (char *) xmalloc (len + 1);
-  strncpy (op->opname, name, len);
-  op->opname[len] = '\0';
+  op = XNEW (opname_e);
+  op->opname = xmemdup0 (name, len);
   return op->opname;
 }
 
@@ -837,7 +867,7 @@ enter_opname (const char *name)
       if (strcmp (op->opname, name) == 0)
        return op->opname;
     }
-  op = (opname_e *) xmalloc (sizeof (opname_e));
+  op = XNEW (opname_e);
   op->opname = xstrdup (name);
   return op->opname;
 }
@@ -866,11 +896,11 @@ clear_opname_map (opname_map *m)
 }
 
 
-static bfd_boolean
+static bool
 same_operand_name (const opname_map_e *m1, const opname_map_e *m2)
 {
-  if (m1->operand_name == NULL || m1->operand_name == NULL)
-    return FALSE;
+  if (m1->operand_name == NULL || m2->operand_name == NULL)
+    return false;
   return (m1->operand_name == m2->operand_name);
 }
 
@@ -889,7 +919,7 @@ get_opmatch (opname_map *map, const char *operand_name)
 }
 
 
-static bfd_boolean
+static bool
 op_is_constant (const opname_map_e *m1)
 {
   return (m1->operand_name == NULL);
@@ -996,14 +1026,14 @@ insn_templ_operand_count (const insn_templ *t)
 
 /* Convert a string to a number.  E.G.: parse_constant("10", &num) */
 
-static bfd_boolean
+static bool
 parse_constant (const char *in, unsigned *val_p)
 {
   unsigned val = 0;
   const char *p;
 
   if (in == NULL)
-    return FALSE;
+    return false;
   p = in;
 
   while (*p != '\0')
@@ -1011,37 +1041,37 @@ parse_constant (const char *in, unsigned *val_p)
       if (*p >= '0' && *p <= '9')
        val = val * 10 + (*p - '0');
       else
-       return FALSE;
+       return false;
       ++p;
     }
   *val_p = val;
-  return TRUE;
+  return true;
 }
 
 
-static bfd_boolean
+static bool
 parse_special_fn (const char *name,
                  const char **fn_name_p,
                  const char **arg_name_p)
 {
-  char *p_start;
+  const char *p_start;
   const char *p_end;
 
   p_start = strchr (name, '(');
   if (p_start == NULL)
-    return FALSE;
+    return false;
 
   p_end = strchr (p_start, ')');
 
   if (p_end == NULL)
-    return FALSE;
+    return false;
 
   if (p_end[1] != '\0')
-    return FALSE;
+    return false;
 
   *fn_name_p = enter_opname_n (name, p_start - name);
   *arg_name_p = enter_opname_n (p_start + 1, p_end - p_start - 1);
-  return TRUE;
+  return true;
 }
 
 
@@ -1088,7 +1118,7 @@ static void
 split_string (split_rec *rec,
              const char *in,
              char c,
-             bfd_boolean elide_whitespace)
+             bool elide_whitespace)
 {
   int cnt = 0;
   int i;
@@ -1107,7 +1137,7 @@ split_string (split_rec *rec,
   if (rec->count == 0)
     return;
 
-  rec->vec = (char **) xmalloc (sizeof (char *) * cnt);
+  rec->vec = XNEWVEC (char *, cnt);
   for (i = 0; i < cnt; i++)
     rec->vec[i] = 0;
 
@@ -1127,9 +1157,7 @@ split_string (split_rec *rec,
       else
        {
          len = p - q;
-         rec->vec[i] = (char *) xmalloc (sizeof (char) * (len + 1));
-         strncpy (rec->vec[i], q, len);
-         rec->vec[i][len] = '\0';
+         rec->vec[i] = xmemdup0 (q, len);
          p++;
        }
 
@@ -1165,7 +1193,7 @@ init_split_rec (split_rec *rec)
 
 /* Parse an instruction template like "insn op1, op2, op3".  */
 
-static bfd_boolean
+static bool
 parse_insn_templ (const char *s, insn_templ *t)
 {
   const char *p = s;
@@ -1180,7 +1208,7 @@ parse_insn_templ (const char *s, insn_templ *t)
   p = skip_white (p);
   insn_name_len = strcspn (s, " ");
   if (insn_name_len == 0)
-    return FALSE;
+    return false;
 
   init_insn_templ (t);
   t->opcode_name = enter_opname_n (p, insn_name_len);
@@ -1188,12 +1216,12 @@ parse_insn_templ (const char *s, insn_templ *t)
   p = p + insn_name_len;
 
   /* Split by ',' and skip beginning and trailing whitespace.  */
-  split_string (&oprec, p, ',', TRUE);
+  split_string (&oprec, p, ',', true);
 
   for (i = 0; i < oprec.count; i++)
     {
       const char *opname = oprec.vec[i];
-      opname_map_e *e = (opname_map_e *) xmalloc (sizeof (opname_map_e));
+      opname_map_e *e = XNEW (opname_map_e);
       e->next = NULL;
       e->operand_name = NULL;
       e->constant_value = 0;
@@ -1211,7 +1239,7 @@ parse_insn_templ (const char *s, insn_templ *t)
              free (e);
              clear_split_rec (&oprec);
              clear_insn_templ (t);
-             return FALSE;
+             return false;
            }
        }
       else
@@ -1221,11 +1249,11 @@ parse_insn_templ (const char *s, insn_templ *t)
       t->operand_map.tail = &e->next;
     }
   clear_split_rec (&oprec);
-  return TRUE;
+  return true;
 }
 
 
-static bfd_boolean
+static bool
 parse_precond (const char *s, precond_e *precond)
 {
   /* All preconditions are currently of the form:
@@ -1247,19 +1275,19 @@ parse_precond (const char *s, precond_e *precond)
   len = strcspn (p, " !=");
 
   if (len == 0)
-    return FALSE;
+    return false;
 
   precond->opname1 = enter_opname_n (p, len);
   p = p + len;
   p = skip_white (p);
 
   /* Check for "==" and "!=".  */
-  if (strncmp (p, "==", 2) == 0)
+  if (startswith (p, "=="))
     precond->cmpop = OP_EQUAL;
-  else if (strncmp (p, "!=", 2) == 0)
+  else if (startswith (p, "!="))
     precond->cmpop = OP_NOTEQUAL;
   else
-    return FALSE;
+    return false;
 
   p = p + 2;
   p = skip_white (p);
@@ -1271,11 +1299,11 @@ parse_precond (const char *s, precond_e *precond)
       if (parse_constant (p, &val))
        precond->opval2 = val;
       else
-       return FALSE;
+       return false;
     }
   else
     precond->opname2 = enter_opname (p);
-  return TRUE;
+  return true;
 }
 
 
@@ -1311,7 +1339,7 @@ clone_req_or_option_list (ReqOrOption *req_or_option)
   if (req_or_option == NULL)
     return NULL;
 
-  new_req_or_option = (ReqOrOption *) xmalloc (sizeof (ReqOrOption));
+  new_req_or_option = XNEW (ReqOrOption);
   new_req_or_option->option_name = xstrdup (req_or_option->option_name);
   new_req_or_option->is_true = req_or_option->is_true;
   new_req_or_option->next = NULL;
@@ -1328,7 +1356,7 @@ clone_req_option_list (ReqOption *req_option)
   if (req_option == NULL)
     return NULL;
 
-  new_req_option = (ReqOption *) xmalloc (sizeof (ReqOption));
+  new_req_option = XNEW (ReqOption);
   new_req_option->or_option_terms = NULL;
   new_req_option->next = NULL;
   new_req_option->or_option_terms =
@@ -1338,7 +1366,7 @@ clone_req_option_list (ReqOption *req_option)
 }
 
 
-static bfd_boolean
+static bool
 parse_option_cond (const char *s, ReqOption *option)
 {
   int i;
@@ -1349,30 +1377,30 @@ parse_option_cond (const char *s, ReqOption *option)
      "Ands" are divided by "?".  */
 
   init_split_rec (&option_term_rec);
-  split_string (&option_term_rec, s, '+', TRUE);
+  split_string (&option_term_rec, s, '+', true);
 
   if (option_term_rec.count == 0)
     {
       clear_split_rec (&option_term_rec);
-      return FALSE;
+      return false;
     }
 
   for (i = 0; i < option_term_rec.count; i++)
     {
       char *option_name = option_term_rec.vec[i];
-      bfd_boolean is_true = TRUE;
+      bool is_true = true;
       ReqOrOption *req;
       ReqOrOption **r_p;
 
-      if (strncmp (option_name, "no-", 3) == 0)
+      if (startswith (option_name, "no-"))
        {
          option_name = xstrdup (&option_name[3]);
-         is_true = FALSE;
+         is_true = false;
        }
       else
        option_name = xstrdup (option_name);
 
-      req = (ReqOrOption *) xmalloc (sizeof (ReqOrOption));
+      req = XNEW (ReqOrOption);
       req->option_name = option_name;
       req->is_true = is_true;
       req->next = NULL;
@@ -1383,7 +1411,7 @@ parse_option_cond (const char *s, ReqOption *option)
        ;
       (*r_p) = req;
     }
-  return TRUE;
+  return true;
 }
 
 
@@ -1403,7 +1431,7 @@ parse_option_cond (const char *s, ReqOption *option)
    split_string, it requires that '|' and '?' are only used as
    delimiters for predicates and required options.  */
 
-static bfd_boolean
+static bool
 parse_insn_pattern (const char *in, insn_pattern *insn)
 {
   split_rec rec;
@@ -1413,41 +1441,41 @@ parse_insn_pattern (const char *in, insn_pattern *insn)
   init_insn_pattern (insn);
 
   init_split_rec (&optionrec);
-  split_string (&optionrec, in, '?', TRUE);
+  split_string (&optionrec, in, '?', true);
   if (optionrec.count == 0)
     {
       clear_split_rec (&optionrec);
-      return FALSE;
+      return false;
     }
 
   init_split_rec (&rec);
 
-  split_string (&rec, optionrec.vec[0], '|', TRUE);
+  split_string (&rec, optionrec.vec[0], '|', true);
 
   if (rec.count == 0)
     {
       clear_split_rec (&rec);
       clear_split_rec (&optionrec);
-      return FALSE;
+      return false;
     }
 
   if (!parse_insn_templ (rec.vec[0], &insn->t))
     {
       clear_split_rec (&rec);
       clear_split_rec (&optionrec);
-      return FALSE;
+      return false;
     }
 
   for (i = 1; i < rec.count; i++)
     {
-      precond_e *cond = (precond_e *) xmalloc (sizeof (precond_e));
+      precond_e *cond = XNEW (precond_e);
 
       if (!parse_precond (rec.vec[i], cond))
        {
          clear_split_rec (&rec);
          clear_split_rec (&optionrec);
          clear_insn_pattern (insn);
-         return FALSE;
+         return false;
        }
 
       /* Append the condition.  */
@@ -1459,7 +1487,7 @@ parse_insn_pattern (const char *in, insn_pattern *insn)
     {
       /* Handle the option conditions.  */
       ReqOption **r_p;
-      ReqOption *req_option = (ReqOption *) xmalloc (sizeof (ReqOption));
+      ReqOption *req_option = XNEW (ReqOption);
       req_option->or_option_terms = NULL;
       req_option->next = NULL;
 
@@ -1469,7 +1497,7 @@ parse_insn_pattern (const char *in, insn_pattern *insn)
          clear_split_rec (&optionrec);
          clear_insn_pattern (insn);
          clear_req_option_list (&req_option);
-         return FALSE;
+         return false;
        }
 
       /* Append the condition.  */
@@ -1481,22 +1509,22 @@ parse_insn_pattern (const char *in, insn_pattern *insn)
 
   clear_split_rec (&rec);
   clear_split_rec (&optionrec);
-  return TRUE;
+  return true;
 }
 
 
-static bfd_boolean
+static bool
 parse_insn_repl (const char *in, insn_repl *r_p)
 {
   /* This is a list of instruction templates separated by ';'.  */
   split_rec rec;
   int i;
 
-  split_string (&rec, in, ';', TRUE);
+  split_string (&rec, in, ';', true);
 
   for (i = 0; i < rec.count; i++)
     {
-      insn_repl_e *e = (insn_repl_e *) xmalloc (sizeof (insn_repl_e));
+      insn_repl_e *e = XNEW (insn_repl_e);
 
       e->next = NULL;
 
@@ -1504,16 +1532,16 @@ parse_insn_repl (const char *in, insn_repl *r_p)
        {
          free (e);
          clear_insn_repl (r_p);
-         return FALSE;
+         return false;
        }
       *r_p->tail = e;
       r_p->tail = &e->next;
     }
-  return TRUE;
+  return true;
 }
 
 
-static bfd_boolean
+static bool
 transition_applies (insn_pattern *initial_insn,
                    const char *from_string ATTRIBUTE_UNUSED,
                    const char *to_string ATTRIBUTE_UNUSED)
@@ -1530,9 +1558,9 @@ transition_applies (insn_pattern *initial_insn,
          || req_or_option->next != NULL)
        continue;
 
-      if (strncmp (req_or_option->option_name, "IsaUse", 6) == 0)
+      if (startswith (req_or_option->option_name, "IsaUse"))
        {
-         bfd_boolean option_available = FALSE;
+         bool option_available = false;
          char *option_name = req_or_option->option_name + 6;
          if (!strcmp (option_name, "DensityInstruction"))
            option_available = (XCHAL_HAVE_DENSITY == 1);
@@ -1543,7 +1571,7 @@ transition_applies (insn_pattern *initial_insn,
          else if (!strcmp (option_name, "Loops"))
            option_available = (XCHAL_HAVE_LOOPS == 1);
          else if (!strcmp (option_name, "WideBranches"))
-           option_available 
+           option_available
              = (XCHAL_HAVE_WIDE_BRANCHES == 1 && produce_flix == FLIX_ALL);
          else if (!strcmp (option_name, "PredictedBranches"))
            option_available
@@ -1555,32 +1583,32 @@ transition_applies (insn_pattern *initial_insn,
            as_warn (_("invalid configuration option '%s' in transition rule '%s'"),
                     req_or_option->option_name, from_string);
          if ((option_available ^ req_or_option->is_true) != 0)
-           return FALSE;
+           return false;
        }
       else if (strcmp (req_or_option->option_name, "realnop") == 0)
        {
-         bfd_boolean nop_available =
+         bool nop_available =
            (xtensa_opcode_lookup (xtensa_default_isa, "nop")
             != XTENSA_UNDEFINED);
          if ((nop_available ^ req_or_option->is_true) != 0)
-           return FALSE;
+           return false;
        }
     }
-  return TRUE;
+  return true;
 }
 
 
-static bfd_boolean
+static bool
 wide_branch_opcode (const char *opcode_name,
-                   char *suffix,
+                   const char *suffix,
                    xtensa_opcode *popcode)
 {
   xtensa_isa isa = xtensa_default_isa;
   xtensa_opcode opcode;
   static char wbr_name_buf[20];
 
-  if (strncmp (opcode_name, "WIDE.", 5) != 0)
-    return FALSE;
+  if (!startswith (opcode_name, "WIDE."))
+    return false;
 
   strcpy (wbr_name_buf, opcode_name + 5);
   strcat (wbr_name_buf, suffix);
@@ -1588,10 +1616,10 @@ wide_branch_opcode (const char *opcode_name,
   if (opcode != XTENSA_UNDEFINED)
     {
       *popcode = opcode;
-      return TRUE;
+      return true;
     }
 
-  return FALSE;
+  return false;
 }
 
 
@@ -1612,7 +1640,7 @@ build_transition (insn_pattern *initial_insn,
   precond_e *precond;
   insn_repl_e *r;
 
-  if (!wide_branch_opcode (initial_insn->t.opcode_name, ".w18", &opcode) 
+  if (!wide_branch_opcode (initial_insn->t.opcode_name, ".w18", &opcode)
       && !wide_branch_opcode (initial_insn->t.opcode_name, ".w15", &opcode))
     opcode = xtensa_opcode_lookup (isa, initial_insn->t.opcode_name);
 
@@ -1632,7 +1660,7 @@ build_transition (insn_pattern *initial_insn,
       return NULL;
     }
 
-  tr = (TransitionRule *) xmalloc (sizeof (TransitionRule));
+  tr = XNEW (TransitionRule);
   tr->opcode = opcode;
   tr->conditions = NULL;
   tr->to_instr = NULL;
@@ -1688,7 +1716,7 @@ build_transition (insn_pattern *initial_insn,
          op2 = get_opmatch (&initial_insn->t.operand_map, precond->opname2);
          if (op2 == NULL)
            as_fatal (_("opcode '%s': no bound opname '%s' "
-                       "for precondition in %s"),
+                       "for precondition in '%s'"),
                      xtensa_opcode_name (isa, opcode),
                      precond->opname2, from_string);
        }
@@ -1727,7 +1755,7 @@ build_transition (insn_pattern *initial_insn,
       const char *fn_name;
       const char *operand_arg_name;
 
-      bi = (BuildInstr *) xmalloc (sizeof (BuildInstr));
+      bi = XNEW (BuildInstr);
       append_build_insn (tr, bi);
 
       bi->opcode = XTENSA_UNDEFINED;
@@ -1769,7 +1797,9 @@ build_transition (insn_pattern *initial_insn,
          /* Check for the right number of ops.  */
          if (xtensa_opcode_num_operands (isa, bi->opcode)
              != (int) operand_count)
-           as_fatal (_("opcode '%s': replacement does not have %d ops"),
+           as_fatal (ngettext ("opcode '%s': replacement does not have %d op",
+                               "opcode '%s': replacement does not have %d ops",
+                               xtensa_opcode_num_operands (isa, bi->opcode)),
                      opcode_name,
                      xtensa_opcode_num_operands (isa, bi->opcode));
        }
@@ -1799,7 +1829,7 @@ build_transition (insn_pattern *initial_insn,
              orig_op = get_opmatch (&initial_insn->t.operand_map,
                                     op->operand_name);
              if (orig_op == NULL)
-               as_fatal (_("opcode %s: unidentified operand '%s' in '%s'"),
+               as_fatal (_("opcode '%s': unidentified operand '%s' in '%s'"),
                          opcode_name, op->operand_name, to_string);
              append_field_op (bi, op->operand_num, orig_op->operand_num);
            }
@@ -1829,13 +1859,13 @@ build_transition (insn_pattern *initial_insn,
              orig_op = get_opmatch (&initial_insn->t.operand_map,
                                     operand_arg_name);
              if (orig_op == NULL)
-               as_fatal (_("opcode %s: unidentified operand '%s' in '%s'"),
+               as_fatal (_("opcode '%s': unidentified operand '%s' in '%s'"),
                          opcode_name, op->operand_name, to_string);
              append_user_fn_field_op (bi, op->operand_num,
                                       typ, orig_op->operand_num);
            }
          else
-           as_fatal (_("opcode %s: could not parse operand '%s' in '%s'"),
+           as_fatal (_("opcode '%s': could not parse operand '%s' in '%s'"),
                      opcode_name, op->operand_name, to_string);
        }
     }
@@ -1857,10 +1887,9 @@ build_transition_table (const string_pattern_pair *transitions,
     return table;
 
   /* Otherwise, build it now.  */
-  table = (TransitionTable *) xmalloc (sizeof (TransitionTable));
+  table = XNEW (TransitionTable);
   table->num_opcodes = num_opcodes;
-  table->table =
-    (TransitionList **) xmalloc (sizeof (TransitionTable *) * num_opcodes);
+  table->table = XNEWVEC (TransitionList *, num_opcodes);
 
   for (i = 0; i < num_opcodes; i++)
     table->table[i] = NULL;