gas/
[deliverable/binutils-gdb.git] / gas / config / tc-xtensa.c
index 11bd8723850a5dbad3f587c478c42f58bf096b14..a44c28093efaedfe64d089c984d397cde0cfa77b 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-xtensa.c -- Assemble Xtensa instructions.
 /* tc-xtensa.c -- Assemble Xtensa instructions.
-   Copyright 2003, 2004 Free Software Foundation, Inc.
+   Copyright 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
 
    This file is part of GAS, the GNU Assembler.
 
@@ -15,8 +15,8 @@
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to
-   the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.  */
+   the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 #include <string.h>
 #include <limits.h>
 
 #include <string.h>
 #include <limits.h>
@@ -76,12 +76,12 @@ bfd_boolean absolute_literals_supported = XSHAL_USE_ABSOLUTE_LITERALS;
 
 static vliw_insn cur_vinsn;
 
 
 static vliw_insn cur_vinsn;
 
-size_t xtensa_fetch_width = XCHAL_INST_FETCH_WIDTH;
+unsigned xtensa_fetch_width = XCHAL_INST_FETCH_WIDTH;
 
 static enum debug_info_type xt_saved_debug_type = DEBUG_NONE;
 
 /* Some functions are only valid in the front end.  This variable
 
 static enum debug_info_type xt_saved_debug_type = DEBUG_NONE;
 
 /* Some functions are only valid in the front end.  This variable
-   allows us to assert that we haven't crossed over into the 
+   allows us to assert that we haven't crossed over into the
    back end.  */
 static bfd_boolean past_xtensa_end = FALSE;
 
    back end.  */
 static bfd_boolean past_xtensa_end = FALSE;
 
@@ -322,20 +322,14 @@ typedef struct op_placement_info_struct
   int num_formats;
   /* A number describing how restrictive the issue is for this
      opcode.  For example, an opcode that fits lots of different
   int num_formats;
   /* A number describing how restrictive the issue is for this
      opcode.  For example, an opcode that fits lots of different
-     formats has a high freedom, as does an opcode that fits 
+     formats has a high freedom, as does an opcode that fits
      only one format but many slots in that format.  The most
      only one format but many slots in that format.  The most
-     restrictive is the opcode that fits only one slot in one 
+     restrictive is the opcode that fits only one slot in one
      format.  */
   int issuef;
      format.  */
   int issuef;
-  /* The single format (i.e., if the op can live in a bundle by itself),
-     narrowest format, and widest format the op can be bundled in 
-     and their sizes:  */
-  xtensa_format single;
   xtensa_format narrowest;
   xtensa_format narrowest;
-  xtensa_format widest;
   char narrowest_size;
   char narrowest_size;
-  char widest_size;
-  char single_size;
+  char narrowest_slot;
 
   /* formats is a bitfield with the Nth bit set
      if the opcode fits in the Nth xtensa_format.  */
 
   /* formats is a bitfield with the Nth bit set
      if the opcode fits in the Nth xtensa_format.  */
@@ -422,7 +416,6 @@ bfd_boolean directive_state[] =
 
 static void xtensa_begin_directive (int);
 static void xtensa_end_directive (int);
 
 static void xtensa_begin_directive (int);
 static void xtensa_end_directive (int);
-static void xtensa_dwarf2_directive_loc (int);
 static void xtensa_literal_prefix (char const *, int);
 static void xtensa_literal_position (int);
 static void xtensa_literal_pseudo (int);
 static void xtensa_literal_prefix (char const *, int);
 static void xtensa_literal_position (int);
 static void xtensa_literal_pseudo (int);
@@ -435,6 +428,8 @@ static bfd_reloc_code_real_type xtensa_elf_suffix (char **, expressionS *);
 
 /* Various Other Internal Functions.  */
 
 
 /* Various Other Internal Functions.  */
 
+extern bfd_boolean xg_is_single_relaxable_insn (TInsn *, TInsn *, bfd_boolean);
+static bfd_boolean xg_build_to_insn (TInsn *, TInsn *, BuildInstr *);
 static void xtensa_mark_literal_pool_location (void);
 static addressT get_expanded_loop_offset (xtensa_opcode);
 static fragS *get_literal_pool_location (segT);
 static void xtensa_mark_literal_pool_location (void);
 static addressT get_expanded_loop_offset (xtensa_opcode);
 static fragS *get_literal_pool_location (segT);
@@ -446,8 +441,9 @@ static int total_frag_text_expansion (fragS *);
 
 /* Alignment Functions.  */
 
 
 /* Alignment Functions.  */
 
-static size_t get_text_align_power (int);
-static addressT get_text_align_max_fill_size (int, bfd_boolean, bfd_boolean);
+static int get_text_align_power (unsigned);
+static int get_text_align_max_fill_size (int, bfd_boolean, bfd_boolean);
+static int branch_align_power (segT);
 
 /* Helpers for xtensa_relax_frag().  */
 
 
 /* Helpers for xtensa_relax_frag().  */
 
@@ -482,6 +478,7 @@ static void init_op_placement_info_table (void);
 extern bfd_boolean opcode_fits_format_slot (xtensa_opcode, xtensa_format, int);
 static int xg_get_single_size (xtensa_opcode);
 static xtensa_format xg_get_single_format (xtensa_opcode);
 extern bfd_boolean opcode_fits_format_slot (xtensa_opcode, xtensa_format, int);
 static int xg_get_single_size (xtensa_opcode);
 static xtensa_format xg_get_single_format (xtensa_opcode);
+static int xg_get_single_slot (xtensa_opcode);
 
 /* TInsn and IStack functions.  */
 
 
 /* TInsn and IStack functions.  */
 
@@ -513,8 +510,6 @@ void set_expr_const (expressionS *, offsetT);
 bfd_boolean expr_is_register (const expressionS *);
 offsetT get_expr_register (const expressionS *);
 void set_expr_symbol_offset (expressionS *, symbolS *, offsetT);
 bfd_boolean expr_is_register (const expressionS *);
 offsetT get_expr_register (const expressionS *);
 void set_expr_symbol_offset (expressionS *, symbolS *, offsetT);
-static void set_expr_symbol_offset_diff
-  (expressionS *, symbolS *, symbolS *, offsetT);
 bfd_boolean expr_is_equal (expressionS *, expressionS *);
 static void copy_expr (expressionS *, const expressionS *);
 
 bfd_boolean expr_is_equal (expressionS *, expressionS *);
 static void copy_expr (expressionS *, const expressionS *);
 
@@ -841,7 +836,7 @@ md_parse_option (int c, char *arg)
       /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
          should be emitted or not.  FIXME: Not implemented.  */
       return 1;
       /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
          should be emitted or not.  FIXME: Not implemented.  */
       return 1;
-      
+
     case option_prefer_l32r:
       if (prefer_const16)
        as_fatal (_("prefer-l32r conflicts with prefer-const16"));
     case option_prefer_l32r:
       if (prefer_const16)
        as_fatal (_("prefer-l32r conflicts with prefer-const16"));
@@ -854,7 +849,7 @@ md_parse_option (int c, char *arg)
       prefer_const16 = 1;
       return 1;
 
       prefer_const16 = 1;
       return 1;
 
-    case option_target_hardware: 
+    case option_target_hardware:
       {
        int earliest, latest = 0;
        if (*arg == 0 || *arg == '-')
       {
        int earliest, latest = 0;
        if (*arg == 0 || *arg == '-')
@@ -947,8 +942,8 @@ xtensa_clear_insn_labels (void)
 }
 
 
 }
 
 
-/* The "loops_ok" argument is provided to allow ignoring labels that 
-   define loop ends.  This fixes a bug where the NOPs to align a 
+/* The "loops_ok" argument is provided to allow ignoring labels that
+   define loop ends.  This fixes a bug where the NOPs to align a
    loop opcode were included in a previous zero-cost loop:
 
    loop a0, loopend
    loop opcode were included in a previous zero-cost loop:
 
    loop a0, loopend
@@ -1013,7 +1008,6 @@ const pseudo_typeS md_pseudo_table[] =
   { "short", xtensa_elf_cons, 2 },
   { "begin", xtensa_begin_directive, 0 },
   { "end", xtensa_end_directive, 0 },
   { "short", xtensa_elf_cons, 2 },
   { "begin", xtensa_begin_directive, 0 },
   { "end", xtensa_end_directive, 0 },
-  { "loc", xtensa_dwarf2_directive_loc, 0 },
   { "literal", xtensa_literal_pseudo, 0 },
   { "frequency", xtensa_frequency_pseudo, 0 },
   { NULL, 0, 0 },
   { "literal", xtensa_literal_pseudo, 0 },
   { "frequency", xtensa_frequency_pseudo, 0 },
   { NULL, 0, 0 },
@@ -1030,21 +1024,12 @@ use_transform (void)
 }
 
 
 }
 
 
-static bfd_boolean
-use_longcalls (void)
-{
-  /* After md_end, you should be checking frag by frag, rather
-     than state directives.  */
-  assert (!past_xtensa_end);
-  return directive_state[directive_longcalls] && use_transform ();
-}
-
-
 static bfd_boolean
 do_align_targets (void)
 {
 static bfd_boolean
 do_align_targets (void)
 {
-  /* After md_end, you should be checking frag by frag, rather
-     than state directives.  */
+  /* Do not use this function after md_end; just look at align_targets
+     instead.  There is no target-align directive, so alignment is either
+     enabled for all frags or not done at all.  */
   assert (!past_xtensa_end);
   return align_targets && use_transform ();
 }
   assert (!past_xtensa_end);
   return align_targets && use_transform ();
 }
@@ -1150,7 +1135,7 @@ get_directive (directiveE *directive, bfd_boolean *negated)
   /* This code is a hack to make .begin [no-][generics|relax] exactly
      equivalent to .begin [no-]transform.  We should remove it when
      we stop accepting those options.  */
   /* This code is a hack to make .begin [no-][generics|relax] exactly
      equivalent to .begin [no-]transform.  We should remove it when
      we stop accepting those options.  */
-     
+
   if (strncmp (input_line_pointer, "generics", strlen ("generics")) == 0)
     {
       as_warn (_("[no-]generics is deprecated; use [no-]transform instead"));
   if (strncmp (input_line_pointer, "generics", strlen ("generics")) == 0)
     {
       as_warn (_("[no-]generics is deprecated; use [no-]transform instead"));
@@ -1160,7 +1145,7 @@ get_directive (directiveE *directive, bfd_boolean *negated)
     {
       as_warn (_("[no-]relax is deprecated; use [no-]transform instead"));
       directive_string = "transform";
     {
       as_warn (_("[no-]relax is deprecated; use [no-]transform instead"));
       directive_string = "transform";
-    }    
+    }
   else
     directive_string = input_line_pointer;
 
   else
     directive_string = input_line_pointer;
 
@@ -1218,7 +1203,7 @@ xtensa_begin_directive (int ignore ATTRIBUTE_UNUSED)
       break;
 
     case directive_literal_prefix:
       break;
 
     case directive_literal_prefix:
-      /* Have to flush pending output because a movi relaxed to an l32r 
+      /* Have to flush pending output because a movi relaxed to an l32r
         might produce a literal.  */
       md_flush_pending_output ();
       /* Check to see if the current fragment is a literal
         might produce a literal.  */
       md_flush_pending_output ();
       /* Check to see if the current fragment is a literal
@@ -1369,8 +1354,7 @@ xtensa_end_directive (int ignore ATTRIBUTE_UNUSED)
              s = (lit_state *) state;
              assert (s);
 
              s = (lit_state *) state;
              assert (s);
 
-             if (use_literal_section)
-               default_lit_sections = *s;
+             default_lit_sections = *s;
 
              /* free the state storage */
              free (s);
 
              /* free the state storage */
              free (s);
@@ -1391,28 +1375,6 @@ xtensa_end_directive (int ignore ATTRIBUTE_UNUSED)
 }
 
 
 }
 
 
-/* Wrap dwarf2 functions so that we correctly support the .loc directive.  */
-
-static bfd_boolean xtensa_loc_directive_seen = FALSE;
-
-static void
-xtensa_dwarf2_directive_loc (int x)
-{
-  xtensa_loc_directive_seen = TRUE;
-  dwarf2_directive_loc (x);
-}
-
-
-static void
-xtensa_dwarf2_emit_insn (int size, struct dwarf2_line_info *loc)
-{
-  if (debug_type != DEBUG_DWARF2 && ! xtensa_loc_directive_seen)
-    return;
-  xtensa_loc_directive_seen = FALSE;
-  dwarf2_gen_line_info (frag_now_fix () - size, loc);
-}
-
-
 /* Place an aligned literal fragment at the current location.  */
 
 static void
 /* Place an aligned literal fragment at the current location.  */
 
 static void
@@ -1933,9 +1895,9 @@ tokenize_arguments (char **args, char *str)
 
          input_line_pointer = arg_end;
          num_args += 1;
 
          input_line_pointer = arg_end;
          num_args += 1;
-         saw_comma = FALSE; 
+         saw_comma = FALSE;
          saw_colon = FALSE;
          saw_colon = FALSE;
-         saw_arg = TRUE; 
+         saw_arg = TRUE;
          break;
        }
     }
          break;
        }
     }
@@ -1952,7 +1914,7 @@ err:
   else if (saw_colon)
     as_bad (_("extra colon"));
   else if (!saw_arg)
   else if (saw_colon)
     as_bad (_("extra colon"));
   else if (!saw_arg)
-    as_bad (_("missing argument"));  
+    as_bad (_("missing argument"));
   else
     as_bad (_("missing comma or colon"));
   input_line_pointer = old_input_line_pointer;
   else
     as_bad (_("missing comma or colon"));
   input_line_pointer = old_input_line_pointer;
@@ -2052,7 +2014,7 @@ parse_arguments (TInsn *insn, int num_args, char **arg_strings)
     goto err;
 
   insn->ntok = tok - insn->tok;
     goto err;
 
   insn->ntok = tok - insn->tok;
-  had_error = FALSE; 
+  had_error = FALSE;
 
  err:
   input_line_pointer = old_input_line_pointer;
 
  err:
   input_line_pointer = old_input_line_pointer;
@@ -2255,7 +2217,7 @@ xg_translate_sysreg_op (char **popname, int *pnum_args, char **arg_strings)
       if (sr == XTENSA_UNDEFINED)
        {
          as_bad (_("invalid register number (%ld) for '%s' instruction"),
       if (sr == XTENSA_UNDEFINED)
        {
          as_bad (_("invalid register number (%ld) for '%s' instruction"),
-                 val, opname);
+                 (long) val, opname);
          return -1;
        }
     }
          return -1;
        }
     }
@@ -2324,7 +2286,7 @@ xtensa_translate_old_userreg_ops (char **popname)
       if (sr == XTENSA_UNDEFINED)
        {
          as_bad (_("invalid register number (%ld) for '%s'"),
       if (sr == XTENSA_UNDEFINED)
        {
          as_bad (_("invalid register number (%ld) for '%s'"),
-                 val, opname);
+                 (long) val, opname);
          return -1;
        }
     }
          return -1;
        }
     }
@@ -2533,7 +2495,7 @@ get_opcode_from_buf (const char *buf, int slot)
       slotbuf = xtensa_insnbuf_alloc (isa);
     }
 
       slotbuf = xtensa_insnbuf_alloc (isa);
     }
 
-  xtensa_insnbuf_from_chars (isa, insnbuf, buf, 0);
+  xtensa_insnbuf_from_chars (isa, insnbuf, (const unsigned char *) buf, 0);
   fmt = xtensa_format_decode (isa, insnbuf);
   if (fmt == XTENSA_UNDEFINED)
     return XTENSA_UNDEFINED;
   fmt = xtensa_format_decode (isa, insnbuf);
   if (fmt == XTENSA_UNDEFINED)
     return XTENSA_UNDEFINED;
@@ -2713,12 +2675,16 @@ xtensa_insnbuf_set_operand (xtensa_insnbuf slotbuf,
       if (xtensa_operand_is_PCrelative (xtensa_default_isa, opcode, operand)
          == 1)
        as_bad_where ((char *) file, line,
       if (xtensa_operand_is_PCrelative (xtensa_default_isa, opcode, operand)
          == 1)
        as_bad_where ((char *) file, line,
-                     _("operand %u is out of range for '%s'"), value,
-                     xtensa_opcode_name (xtensa_default_isa, opcode));
+                     _("operand %d of '%s' has out of range value '%u'"), 
+                     operand + 1,
+                     xtensa_opcode_name (xtensa_default_isa, opcode),
+                     value);
       else
        as_bad_where ((char *) file, line,
       else
        as_bad_where ((char *) file, line,
-                     _("operand %u is invalid for '%s'"), value,
-                     xtensa_opcode_name (xtensa_default_isa, opcode));
+                     _("operand %d of '%s' has invalid value '%u'"),
+                     operand + 1,
+                     xtensa_opcode_name (xtensa_default_isa, opcode),
+                     value);
       return;
     }
 
       return;
     }
 
@@ -2992,52 +2958,23 @@ is_unique_insn_expansion (TransitionRule *r)
 }
 
 
 }
 
 
-static int
-xg_get_build_instr_size (BuildInstr *insn)
-{
-  assert (insn->typ == INSTR_INSTR);
-  return xg_get_single_size (insn->opcode);
-}
-
+/* Check if there is exactly one relaxation for INSN that converts it to
+   another instruction of equal or larger size.  If so, and if TARG is
+   non-null, go ahead and generate the relaxed instruction into TARG.  If
+   NARROW_ONLY is true, then only consider relaxations that widen a narrow
+   instruction, i.e., ignore relaxations that convert to an instruction of
+   equal size.  In some contexts where this function is used, only
+   a single widening is allowed and the NARROW_ONLY argument is used to
+   exclude cases like ADDI being "widened" to an ADDMI, which may
+   later be relaxed to an ADDMI/ADDI pair.  */
 
 
-static bfd_boolean
-xg_is_narrow_insn (TInsn *insn)
+bfd_boolean
+xg_is_single_relaxable_insn (TInsn *insn, TInsn *targ, bfd_boolean narrow_only)
 {
   TransitionTable *table = xg_build_widen_table (&transition_rule_cmp);
   TransitionList *l;
 {
   TransitionTable *table = xg_build_widen_table (&transition_rule_cmp);
   TransitionList *l;
-  int num_match = 0;
-  assert (insn->insn_type == ITYPE_INSN);
-  assert (insn->opcode < table->num_opcodes);
-
-  for (l = table->table[insn->opcode]; l != NULL; l = l->next)
-    {
-      TransitionRule *rule = l->rule;
-
-      if (xg_instruction_matches_rule (insn, rule)
-         && is_unique_insn_expansion (rule))
-       {
-         /* It only generates one instruction... */
-         assert (insn->insn_type == ITYPE_INSN);
-         /* ...and it is a larger instruction.  */
-         if (xg_get_single_size (insn->opcode)
-             < xg_get_build_instr_size (rule->to_instr))
-           {
-             num_match++;
-             if (num_match > 1)
-               return FALSE;
-           }
-       }
-    }
-  return (num_match == 1);
-}
-
+  TransitionRule *match = 0;
 
 
-static bfd_boolean
-xg_is_single_relaxable_insn (TInsn *insn)
-{
-  TransitionTable *table = xg_build_widen_table (&transition_rule_cmp);
-  TransitionList *l;
-  int num_match = 0;
   assert (insn->insn_type == ITYPE_INSN);
   assert (insn->opcode < table->num_opcodes);
 
   assert (insn->insn_type == ITYPE_INSN);
   assert (insn->opcode < table->num_opcodes);
 
@@ -3046,21 +2983,21 @@ xg_is_single_relaxable_insn (TInsn *insn)
       TransitionRule *rule = l->rule;
 
       if (xg_instruction_matches_rule (insn, rule)
       TransitionRule *rule = l->rule;
 
       if (xg_instruction_matches_rule (insn, rule)
-         && is_unique_insn_expansion (rule))
+         && is_unique_insn_expansion (rule)
+         && (xg_get_single_size (insn->opcode) + (narrow_only ? 1 : 0)
+             <= xg_get_single_size (rule->to_instr->opcode)))
        {
        {
-         /* It only generates one instruction... */
-         assert (insn->insn_type == ITYPE_INSN);
-         /* ... and it is a larger instruction.  */
-         if (xg_get_single_size (insn->opcode)
-             <= xg_get_build_instr_size (rule->to_instr))
-           {
-             num_match++;
-             if (num_match > 1)
-               return FALSE;
-           }
+         if (match)
+           return FALSE;
+         match = rule;
        }
     }
        }
     }
-  return (num_match == 1);
+  if (!match)
+    return FALSE;
+
+  if (targ)
+    xg_build_to_insn (targ, insn, match->to_instr);
+  return TRUE;
 }
 
 
 }
 
 
@@ -3312,22 +3249,28 @@ xg_symbolic_immeds_fit (const TInsn *insn,
          break;
 
        case O_symbol:
          break;
 
        case O_symbol:
-         /* We only allow symbols for pc-relative stuff.
+         /* We only allow symbols for PC-relative references.
             If pc_frag == 0, then we don't have frag locations yet.  */
             If pc_frag == 0, then we don't have frag locations yet.  */
-         if (pc_frag == 0)
+         if (pc_frag == 0
+             || xtensa_operand_is_PCrelative (isa, insn->opcode, i) == 0)
            return FALSE;
 
            return FALSE;
 
-         /* If it is PC-relative and the symbol is not in the same 
-            segment as the PC.... */
-         if (xtensa_operand_is_PCrelative (isa, insn->opcode, i) == 0
-             || S_GET_SEGMENT (expr->X_add_symbol) != pc_seg)
+         /* If it is a weak symbol, then assume it won't reach.  */
+         if (S_IS_WEAK (expr->X_add_symbol))
            return FALSE;
 
            return FALSE;
 
-         /* If it is a weak symbol, then assume it won't reach.  This will
-            only affect calls when longcalls are enabled, because if
-            longcalls are disabled, then the call is marked as a specific
-            opcode.  */
-         if (S_IS_WEAK (expr->X_add_symbol))
+         if (is_direct_call_opcode (insn->opcode)
+             && ! pc_frag->tc_frag_data.use_longcalls)
+           {
+             /* If callee is undefined or in a different segment, be
+                optimistic and assume it will be in range.  */
+             if (S_GET_SEGMENT (expr->X_add_symbol) != pc_seg)
+               return TRUE;
+           }
+
+         /* Only references within a segment can be known to fit in the
+            operands at assembly time.  */
+         if (S_GET_SEGMENT (expr->X_add_symbol) != pc_seg)
            return FALSE;
 
          symbolP = expr->X_add_symbol;
            return FALSE;
 
          symbolP = expr->X_add_symbol;
@@ -3347,7 +3290,7 @@ xg_symbolic_immeds_fit (const TInsn *insn,
            {
              target += stretch;
            }
            {
              target += stretch;
            }
+
          new_offset = target;
          xtensa_operand_do_reloc (isa, insn->opcode, i, &new_offset, pc);
          if (xg_check_operand (new_offset, insn->opcode, i))
          new_offset = target;
          xtensa_operand_do_reloc (isa, insn->opcode, i, &new_offset, pc);
          if (xg_check_operand (new_offset, insn->opcode, i))
@@ -3373,7 +3316,7 @@ xg_build_to_insn (TInsn *targ, TInsn *insn, BuildInstr *bi)
   symbolS *sym;
 
   memset (targ, 0, sizeof (TInsn));
   symbolS *sym;
 
   memset (targ, 0, sizeof (TInsn));
-  targ->loc = insn->loc;
+  targ->linenum = insn->linenum;
   switch (bi->typ)
     {
     case INSTR_INSTR:
   switch (bi->typ)
     {
     case INSTR_INSTR:
@@ -3582,34 +3525,6 @@ xg_expand_to_stack (IStack *istack, TInsn *insn, int lateral_steps)
   return FALSE;
 }
 
   return FALSE;
 }
 
-
-static bfd_boolean
-xg_expand_narrow (TInsn *targ, TInsn *insn)
-{
-  TransitionTable *table = xg_build_widen_table (&transition_rule_cmp);
-  TransitionList *l;
-
-  assert (insn->insn_type == ITYPE_INSN);
-  assert (insn->opcode < table->num_opcodes);
-
-  for (l = table->table[insn->opcode]; l != NULL; l = l->next)
-    {
-      TransitionRule *rule = l->rule;
-      if (xg_instruction_matches_rule (insn, rule)
-         && is_unique_insn_expansion (rule))
-       {
-         /* Is it a larger instruction?  */
-         if (xg_get_single_size (insn->opcode)
-             <= xg_get_build_instr_size (rule->to_instr))
-           {
-             xg_build_to_insn (targ, insn, rule->to_instr);
-             return FALSE;
-           }
-       }
-    }
-  return TRUE;
-}
-
 \f
 /* Relax the assembly instruction at least "min_steps".
    Return the number of steps taken.  */
 \f
 /* Relax the assembly instruction at least "min_steps".
    Return the number of steps taken.  */
@@ -3645,17 +3560,13 @@ xg_assembly_relax (IStack *istack,
     }
   current_insn = *insn;
 
     }
   current_insn = *insn;
 
-  /* Walk through all of the single instruction expansions. */
-  while (xg_is_single_relaxable_insn (&current_insn))
+  /* Walk through all of the single instruction expansions.  */
+  while (xg_is_single_relaxable_insn (&current_insn, &single_target, FALSE))
     {
     {
-      int error_val = xg_expand_narrow (&single_target, &current_insn);
-
-      assert (!error_val);
-
+      steps_taken++;
       if (xg_symbolic_immeds_fit (&single_target, pc_seg, pc_frag, pc_offset,
                                  stretch))
        {
       if (xg_symbolic_immeds_fit (&single_target, pc_seg, pc_frag, pc_offset,
                                  stretch))
        {
-         steps_taken++;
          if (steps_taken >= min_steps)
            {
              istack_push (istack, &single_target);
          if (steps_taken >= min_steps)
            {
              istack_push (istack, &single_target);
@@ -3804,7 +3715,7 @@ is_branch_jmp_to_next (TInsn *insn, fragS *fragP)
   if (target_frag == NULL)
     return FALSE;
 
   if (target_frag == NULL)
     return FALSE;
 
-  if (is_next_frag_target (fragP->fr_next, target_frag) 
+  if (is_next_frag_target (fragP->fr_next, target_frag)
       && S_GET_VALUE (sym) == target_frag->fr_address)
     return TRUE;
 
       && S_GET_VALUE (sym) == target_frag->fr_address)
     return TRUE;
 
@@ -3861,13 +3772,13 @@ xg_build_token_insn (BuildInstr *instr_spec, TInsn *old_insn, TInsn *new_insn)
       new_insn->insn_type = ITYPE_INSN;
       new_insn->opcode = instr_spec->opcode;
       new_insn->is_specific_opcode = FALSE;
       new_insn->insn_type = ITYPE_INSN;
       new_insn->opcode = instr_spec->opcode;
       new_insn->is_specific_opcode = FALSE;
-      new_insn->loc = old_insn->loc;
+      new_insn->linenum = old_insn->linenum;
       break;
     case INSTR_LITERAL_DEF:
       new_insn->insn_type = ITYPE_LITERAL;
       new_insn->opcode = XTENSA_UNDEFINED;
       new_insn->is_specific_opcode = FALSE;
       break;
     case INSTR_LITERAL_DEF:
       new_insn->insn_type = ITYPE_LITERAL;
       new_insn->opcode = XTENSA_UNDEFINED;
       new_insn->is_specific_opcode = FALSE;
-      new_insn->loc = old_insn->loc;
+      new_insn->linenum = old_insn->linenum;
       break;
     case INSTR_LABEL_DEF:
       as_bad (_("INSTR_LABEL_DEF not supported yet"));
       break;
     case INSTR_LABEL_DEF:
       as_bad (_("INSTR_LABEL_DEF not supported yet"));
@@ -3943,15 +3854,16 @@ xg_simplify_insn (TInsn *old_insn, TInsn *new_insn)
 
 /* xg_expand_assembly_insn: (1) Simplify the instruction, i.e., l32i ->
    l32i.n. (2) Check the number of operands.  (3) Place the instruction
 
 /* xg_expand_assembly_insn: (1) Simplify the instruction, i.e., l32i ->
    l32i.n. (2) Check the number of operands.  (3) Place the instruction
-   tokens into the stack or if we can relax it at assembly time, place
-   multiple instructions/literals onto the stack.  Return FALSE if no
-   error.  */
+   tokens into the stack or relax it and place multiple
+   instructions/literals onto the stack.  Return FALSE if no error.  */
 
 static bfd_boolean
 xg_expand_assembly_insn (IStack *istack, TInsn *orig_insn)
 {
   int noperands;
   TInsn new_insn;
 
 static bfd_boolean
 xg_expand_assembly_insn (IStack *istack, TInsn *orig_insn)
 {
   int noperands;
   TInsn new_insn;
+  bfd_boolean do_expand;
+
   memset (&new_insn, 0, sizeof (TInsn));
 
   /* Narrow it if we can.  xg_simplify_insn now does all the
   memset (&new_insn, 0, sizeof (TInsn));
 
   /* Narrow it if we can.  xg_simplify_insn now does all the
@@ -3977,50 +3889,37 @@ xg_expand_assembly_insn (IStack *istack, TInsn *orig_insn)
 
   /* If there are not enough operands, we will assert above.  If there
      are too many, just cut out the extras here.  */
 
   /* If there are not enough operands, we will assert above.  If there
      are too many, just cut out the extras here.  */
-
   orig_insn->ntok = noperands;
 
   orig_insn->ntok = noperands;
 
-  /* Cases:
-
-     Instructions with all constant immeds:
-     Assemble them and relax the instruction if possible.
-     Give error if not possible; no fixup needed.
-
-     Instructions with symbolic immeds:
-     Assemble them with a Fix up (that may cause instruction expansion).
-     Also close out the fragment if the fixup may cause instruction expansion.
-
-     There are some other special cases where we need alignment.
-     1) before certain instructions with required alignment (OPCODE_ALIGN)
-     2) before labels that have jumps (LABEL_ALIGN)
-     3) after call instructions (RETURN_ALIGN)
-        Multiple of these may be possible on the same fragment.
-       If so, make sure to satisfy the required alignment.
-       Then try to get the desired alignment.  */
-
   if (tinsn_has_invalid_symbolic_operands (orig_insn))
     return TRUE;
 
   if (tinsn_has_invalid_symbolic_operands (orig_insn))
     return TRUE;
 
-  if (orig_insn->is_specific_opcode || !use_transform ())
-    {
-      istack_push (istack, orig_insn);
-      return FALSE;
-    }
+  /* If the instruction will definitely need to be relaxed, it is better
+     to expand it now for better scheduling.  Decide whether to expand
+     now....  */
+  do_expand = (!orig_insn->is_specific_opcode && use_transform ());
+
+  /* Calls should be expanded to longcalls only in the backend relaxation
+     so that the assembly scheduler will keep the L32R/CALLX instructions
+     adjacent.  */
+  if (is_direct_call_opcode (orig_insn->opcode))
+    do_expand = FALSE;
 
   if (tinsn_has_symbolic_operands (orig_insn))
     {
 
   if (tinsn_has_symbolic_operands (orig_insn))
     {
-      if (tinsn_has_complex_operands (orig_insn))
-       xg_assembly_relax (istack, orig_insn, 0, 0, 0, 0, 0);
-      else
-       istack_push (istack, orig_insn);
+      /* The values of symbolic operands are not known yet, so only expand
+        now if an operand is "complex" (e.g., difference of symbols) and
+        will have to be stored as a literal regardless of the value.  */
+      if (!tinsn_has_complex_operands (orig_insn))
+       do_expand = FALSE;
     }
     }
+  else if (xg_immeds_fit (orig_insn))
+    do_expand = FALSE;
+
+  if (do_expand)
+    xg_assembly_relax (istack, orig_insn, 0, 0, 0, 0, 0);
   else
   else
-    {
-      if (xg_immeds_fit (orig_insn))
-       istack_push (istack, orig_insn);
-      else
-       xg_assembly_relax (istack, orig_insn, 0, 0, 0, 0, 0);
-    }
+    istack_push (istack, orig_insn);
 
   return FALSE;
 }
 
   return FALSE;
 }
@@ -4119,7 +4018,7 @@ xg_assemble_literal (/* const */ TInsn *insn)
       if (size > litsize)
        {
          /* This happens when someone writes a "movi a2, big_number".  */
       if (size > litsize)
        {
          /* This happens when someone writes a "movi a2, big_number".  */
-         as_bad_where (frag_now->fr_file, frag_now->fr_line, 
+         as_bad_where (frag_now->fr_file, frag_now->fr_line,
                        _("invalid immediate"));
          xtensa_restore_emit_state (&state);
          return NULL;
                        _("invalid immediate"));
          xtensa_restore_emit_state (&state);
          return NULL;
@@ -4232,7 +4131,7 @@ xg_add_opcode_fix (TInsn *tinsn,
   if (opnum != get_relaxable_immed (opcode))
     {
       as_bad (_("invalid relocation for operand %i of '%s'"),
   if (opnum != get_relaxable_immed (opcode))
     {
       as_bad (_("invalid relocation for operand %i of '%s'"),
-             opnum, xtensa_opcode_name (xtensa_default_isa, opcode));
+             opnum + 1, xtensa_opcode_name (xtensa_default_isa, opcode));
       return FALSE;
     }
 
       return FALSE;
     }
 
@@ -4242,7 +4141,7 @@ xg_add_opcode_fix (TInsn *tinsn,
   if (expr->X_op == O_lo16 || expr->X_op == O_hi16)
     {
       as_bad (_("invalid expression for operand %i of '%s'"),
   if (expr->X_op == O_lo16 || expr->X_op == O_hi16)
     {
       as_bad (_("invalid expression for operand %i of '%s'"),
-             opnum, xtensa_opcode_name (xtensa_default_isa, opcode));
+             opnum + 1, xtensa_opcode_name (xtensa_default_isa, opcode));
       return FALSE;
     }
 
       return FALSE;
     }
 
@@ -4266,6 +4165,7 @@ xg_add_opcode_fix (TInsn *tinsn,
   fmt_length = xtensa_format_length (xtensa_default_isa, fmt);
   the_fix = fix_new_exp (fragP, offset, fmt_length, expr,
                         howto->pc_relative, reloc);
   fmt_length = xtensa_format_length (xtensa_default_isa, fmt);
   the_fix = fix_new_exp (fragP, offset, fmt_length, expr,
                         howto->pc_relative, reloc);
+  the_fix->fx_no_overflow = 1;
 
   if (expr->X_add_symbol
       && (S_IS_EXTERNAL (expr->X_add_symbol)
 
   if (expr->X_add_symbol
       && (S_IS_EXTERNAL (expr->X_add_symbol)
@@ -4275,14 +4175,13 @@ xg_add_opcode_fix (TInsn *tinsn,
   the_fix->tc_fix_data.X_add_symbol = expr->X_add_symbol;
   the_fix->tc_fix_data.X_add_number = expr->X_add_number;
   the_fix->tc_fix_data.slot = slot;
   the_fix->tc_fix_data.X_add_symbol = expr->X_add_symbol;
   the_fix->tc_fix_data.X_add_number = expr->X_add_number;
   the_fix->tc_fix_data.slot = slot;
-  
+
   return TRUE;
 }
 
 
 static bfd_boolean
 xg_emit_insn_to_buf (TInsn *tinsn,
   return TRUE;
 }
 
 
 static bfd_boolean
 xg_emit_insn_to_buf (TInsn *tinsn,
-                    xtensa_format fmt,
                     char *buf,
                     fragS *fragP,
                     offsetT offset,
                     char *buf,
                     fragS *fragP,
                     offsetT offset,
@@ -4291,6 +4190,7 @@ xg_emit_insn_to_buf (TInsn *tinsn,
   static xtensa_insnbuf insnbuf = NULL;
   bfd_boolean has_symbolic_immed = FALSE;
   bfd_boolean ok = TRUE;
   static xtensa_insnbuf insnbuf = NULL;
   bfd_boolean has_symbolic_immed = FALSE;
   bfd_boolean ok = TRUE;
+
   if (!insnbuf)
     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 
   if (!insnbuf)
     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 
@@ -4298,14 +4198,17 @@ xg_emit_insn_to_buf (TInsn *tinsn,
   if (has_symbolic_immed && build_fix)
     {
       /* Add a fixup.  */
   if (has_symbolic_immed && build_fix)
     {
       /* Add a fixup.  */
+      xtensa_format fmt = xg_get_single_format (tinsn->opcode);
+      int slot = xg_get_single_slot (tinsn->opcode);
       int opnum = get_relaxable_immed (tinsn->opcode);
       expressionS *exp = &tinsn->tok[opnum];
 
       int opnum = get_relaxable_immed (tinsn->opcode);
       expressionS *exp = &tinsn->tok[opnum];
 
-      if (!xg_add_opcode_fix (tinsn, opnum, fmt, 0, exp, fragP, offset))
+      if (!xg_add_opcode_fix (tinsn, opnum, fmt, slot, exp, fragP, offset))
        ok = FALSE;
     }
   fragP->tc_frag_data.is_insn = TRUE;
        ok = FALSE;
     }
   fragP->tc_frag_data.is_insn = TRUE;
-  xtensa_insnbuf_to_chars (xtensa_default_isa, insnbuf, buf, 0);
+  xtensa_insnbuf_to_chars (xtensa_default_isa, insnbuf,
+                          (unsigned char *) buf, 0);
   return ok;
 }
 
   return ok;
 }
 
@@ -4395,7 +4298,7 @@ is_bad_loopend_opcode (const TInsn *tinsn)
       || opcode == xtensa_waiti_opcode
       || opcode == xtensa_rsr_lcount_opcode)
     return TRUE;
       || opcode == xtensa_waiti_opcode
       || opcode == xtensa_rsr_lcount_opcode)
     return TRUE;
-  
+
   return FALSE;
 }
 
   return FALSE;
 }
 
@@ -4437,7 +4340,7 @@ next_non_empty_frag (const fragS *fragP)
 {
   fragS *next_fragP = fragP->fr_next;
 
 {
   fragS *next_fragP = fragP->fr_next;
 
-  /* Sometimes an empty will end up here due storage allocation issues. 
+  /* Sometimes an empty will end up here due storage allocation issues.
      So we have to skip until we find something legit.  */
   while (next_fragP && next_fragP->fr_fix == 0)
     next_fragP = next_fragP->fr_next;
      So we have to skip until we find something legit.  */
   while (next_fragP && next_fragP->fr_fix == 0)
     next_fragP = next_fragP->fr_next;
@@ -4474,7 +4377,7 @@ frag_format_size (const fragS *fragP)
   static xtensa_insnbuf insnbuf = NULL;
   xtensa_isa isa = xtensa_default_isa;
   xtensa_format fmt;
   static xtensa_insnbuf insnbuf = NULL;
   xtensa_isa isa = xtensa_default_isa;
   xtensa_format fmt;
-  int fmt_size; 
+  int fmt_size;
 
   if (!insnbuf)
     insnbuf = xtensa_insnbuf_alloc (isa);
 
   if (!insnbuf)
     insnbuf = xtensa_insnbuf_alloc (isa);
@@ -4482,7 +4385,8 @@ frag_format_size (const fragS *fragP)
   if (fragP == NULL)
     return XTENSA_UNDEFINED;
 
   if (fragP == NULL)
     return XTENSA_UNDEFINED;
 
-  xtensa_insnbuf_from_chars (isa, insnbuf, fragP->fr_literal, 0);
+  xtensa_insnbuf_from_chars (isa, insnbuf,
+                            (unsigned char *) fragP->fr_literal, 0);
 
   fmt = xtensa_format_decode (isa, insnbuf);
   if (fmt == XTENSA_UNDEFINED)
 
   fmt = xtensa_format_decode (isa, insnbuf);
   if (fmt == XTENSA_UNDEFINED)
@@ -4494,7 +4398,7 @@ frag_format_size (const fragS *fragP)
   if (fragP->fr_opcode != fragP->fr_literal)
     return fmt_size;
 
   if (fragP->fr_opcode != fragP->fr_literal)
     return fmt_size;
 
-  /* If during relaxation we have to pull an instruction out of a 
+  /* If during relaxation we have to pull an instruction out of a
      multi-slot instruction, we will return the more conservative
      number.  This works because alignment on bigger instructions
      is more restrictive than alignment on smaller instructions.
      multi-slot instruction, we will return the more conservative
      number.  This works because alignment on bigger instructions
      is more restrictive than alignment on smaller instructions.
@@ -4515,7 +4419,7 @@ frag_format_size (const fragS *fragP)
   if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP1
       || fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP2)
     return 3;
   if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP1
       || fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP2)
     return 3;
-  
+
   if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
     return 2 + fragP->tc_frag_data.text_expansion[0];
 
   if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
     return 2 + fragP->tc_frag_data.text_expansion[0];
 
@@ -4540,7 +4444,7 @@ update_next_frag_state (fragS *fragP)
   fragS *next_fragP = fragP->fr_next;
   fragS *new_target = NULL;
 
   fragS *next_fragP = fragP->fr_next;
   fragS *new_target = NULL;
 
-  if (align_targets) 
+  if (align_targets)
     {
       /* We are guaranteed there will be one of these...   */
       while (!(next_fragP->fr_type == rs_machine_dependent
     {
       /* We are guaranteed there will be one of these...   */
       while (!(next_fragP->fr_type == rs_machine_dependent
@@ -4597,7 +4501,7 @@ next_frag_is_branch_target (const fragS *fragP)
 static bfd_boolean
 next_frag_is_loop_target (const fragS *fragP)
 {
 static bfd_boolean
 next_frag_is_loop_target (const fragS *fragP)
 {
-  /* Sometimes an empty will end up here due storage allocation issues. 
+  /* Sometimes an empty will end up here due storage allocation issues.
      So we have to skip until we find something legit. */
   for (fragP = fragP->fr_next; fragP; fragP = fragP->fr_next)
     {
      So we have to skip until we find something legit. */
   for (fragP = fragP->fr_next; fragP; fragP = fragP->fr_next)
     {
@@ -4656,15 +4560,15 @@ xtensa_mark_literal_pool_location (void)
   frag_align (2, 0, 0);
   record_alignment (now_seg, 2);
 
   frag_align (2, 0, 0);
   record_alignment (now_seg, 2);
 
-  /* We stash info in the fr_var of these frags
-     so we can later move the literal's fixes into this
-     frchain's fix list.  We can use fr_var because fr_var's
-     interpretation depends solely on the fr_type and subtype.  */
+  /* We stash info in these frags so we can later move the literal's
+     fixes into this frchain's fix list.  */
   pool_location = frag_now;
   pool_location = frag_now;
-  frag_variant (rs_machine_dependent, 0, (int) frchain_now,
+  frag_now->tc_frag_data.lit_frchain = frchain_now;
+  frag_variant (rs_machine_dependent, 0, 0,
                RELAX_LITERAL_POOL_BEGIN, NULL, 0, NULL);
   xtensa_set_frag_assembly_state (frag_now);
                RELAX_LITERAL_POOL_BEGIN, NULL, 0, NULL);
   xtensa_set_frag_assembly_state (frag_now);
-  frag_variant (rs_machine_dependent, 0, (int) now_seg,
+  frag_now->tc_frag_data.lit_seg = now_seg;
+  frag_variant (rs_machine_dependent, 0, 0,
                RELAX_LITERAL_POOL_END, NULL, 0, NULL);
   xtensa_set_frag_assembly_state (frag_now);
 
                RELAX_LITERAL_POOL_END, NULL, 0, NULL);
   xtensa_set_frag_assembly_state (frag_now);
 
@@ -4720,7 +4624,7 @@ build_nop (TInsn *tinsn, int size)
    allocated "buf" with at least "size" bytes.  */
 
 static void
    allocated "buf" with at least "size" bytes.  */
 
 static void
-assemble_nop (size_t size, char *buf)
+assemble_nop (int size, char *buf)
 {
   static xtensa_insnbuf insnbuf = NULL;
   TInsn tinsn;
 {
   static xtensa_insnbuf insnbuf = NULL;
   TInsn tinsn;
@@ -4731,7 +4635,8 @@ assemble_nop (size_t size, char *buf)
     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 
   tinsn_to_insnbuf (&tinsn, insnbuf);
     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
 
   tinsn_to_insnbuf (&tinsn, insnbuf);
-  xtensa_insnbuf_to_chars (xtensa_default_isa, insnbuf, buf, 0);
+  xtensa_insnbuf_to_chars (xtensa_default_isa, insnbuf,
+                          (unsigned char *) buf, 0);
 }
 
 
 }
 
 
@@ -4784,10 +4689,12 @@ xtensa_set_frag_assembly_state (fragS *fragP)
     fragP->tc_frag_data.is_no_density = TRUE;
 
   /* This function is called from subsegs_finish, which is called
     fragP->tc_frag_data.is_no_density = TRUE;
 
   /* This function is called from subsegs_finish, which is called
-     after xtensa_end, so we can't use "use_transform" or 
+     after xtensa_end, so we can't use "use_transform" or
      "use_schedule" here.  */
   if (!directive_state[directive_transform])
     fragP->tc_frag_data.is_no_transform = TRUE;
      "use_schedule" here.  */
   if (!directive_state[directive_transform])
     fragP->tc_frag_data.is_no_transform = TRUE;
+  if (directive_state[directive_longcalls])
+    fragP->tc_frag_data.use_longcalls = TRUE;
   fragP->tc_frag_data.use_absolute_literals =
     directive_state[directive_absolute_literals];
   fragP->tc_frag_data.is_assembly_state_set = TRUE;
   fragP->tc_frag_data.use_absolute_literals =
     directive_state[directive_absolute_literals];
   fragP->tc_frag_data.is_assembly_state_set = TRUE;
@@ -4846,6 +4753,8 @@ xtensa_find_unmarked_state_frags (void)
                        last_fragP->tc_frag_data.is_no_density;
                      fragP->tc_frag_data.is_no_transform =
                        last_fragP->tc_frag_data.is_no_transform;
                        last_fragP->tc_frag_data.is_no_density;
                      fragP->tc_frag_data.is_no_transform =
                        last_fragP->tc_frag_data.is_no_transform;
+                     fragP->tc_frag_data.use_longcalls =
+                       last_fragP->tc_frag_data.use_longcalls;
                      fragP->tc_frag_data.use_absolute_literals =
                        last_fragP->tc_frag_data.use_absolute_literals;
                    }
                      fragP->tc_frag_data.use_absolute_literals =
                        last_fragP->tc_frag_data.use_absolute_literals;
                    }
@@ -4866,9 +4775,9 @@ xtensa_find_unaligned_branch_targets (bfd *abfd ATTRIBUTE_UNUSED,
   flagword flags = bfd_get_section_flags (abfd, sec);
   segment_info_type *seginfo = seg_info (sec);
   fragS *frag = seginfo->frchainP->frch_root;
   flagword flags = bfd_get_section_flags (abfd, sec);
   segment_info_type *seginfo = seg_info (sec);
   fragS *frag = seginfo->frchainP->frch_root;
-  
+
   if (flags & SEC_CODE)
   if (flags & SEC_CODE)
-    {  
+    {
       xtensa_isa isa = xtensa_default_isa;
       xtensa_insnbuf insnbuf = xtensa_insnbuf_alloc (isa);
       while (frag != NULL)
       xtensa_isa isa = xtensa_default_isa;
       xtensa_insnbuf insnbuf = xtensa_insnbuf_alloc (isa);
       while (frag != NULL)
@@ -4876,17 +4785,19 @@ xtensa_find_unaligned_branch_targets (bfd *abfd ATTRIBUTE_UNUSED,
          if (frag->tc_frag_data.is_branch_target)
            {
              int op_size;
          if (frag->tc_frag_data.is_branch_target)
            {
              int op_size;
-             int frag_addr;
+             addressT branch_align, frag_addr;
              xtensa_format fmt;
 
              xtensa_format fmt;
 
-             xtensa_insnbuf_from_chars (isa, insnbuf, frag->fr_literal, 0);
+             xtensa_insnbuf_from_chars
+               (isa, insnbuf, (unsigned char *) frag->fr_literal, 0);
              fmt = xtensa_format_decode (isa, insnbuf);
              op_size = xtensa_format_length (isa, fmt);
              fmt = xtensa_format_decode (isa, insnbuf);
              op_size = xtensa_format_length (isa, fmt);
-             frag_addr = frag->fr_address % xtensa_fetch_width;
-             if (frag_addr + op_size > (int) xtensa_fetch_width)
+             branch_align = 1 << branch_align_power (sec);
+             frag_addr = frag->fr_address % branch_align;
+             if (frag_addr + op_size > branch_align)
                as_warn_where (frag->fr_file, frag->fr_line,
                               _("unaligned branch target: %d bytes at 0x%lx"),
                as_warn_where (frag->fr_file, frag->fr_line,
                               _("unaligned branch target: %d bytes at 0x%lx"),
-                              op_size, frag->fr_address);
+                              op_size, (long) frag->fr_address);
            }
          frag = frag->fr_next;
        }
            }
          frag = frag->fr_next;
        }
@@ -4904,27 +4815,28 @@ xtensa_find_unaligned_loops (bfd *abfd ATTRIBUTE_UNUSED,
   segment_info_type *seginfo = seg_info (sec);
   fragS *frag = seginfo->frchainP->frch_root;
   xtensa_isa isa = xtensa_default_isa;
   segment_info_type *seginfo = seg_info (sec);
   fragS *frag = seginfo->frchainP->frch_root;
   xtensa_isa isa = xtensa_default_isa;
-  
+
   if (flags & SEC_CODE)
   if (flags & SEC_CODE)
-    {  
+    {
       xtensa_insnbuf insnbuf = xtensa_insnbuf_alloc (isa);
       while (frag != NULL)
        {
          if (frag->tc_frag_data.is_first_loop_insn)
            {
              int op_size;
       xtensa_insnbuf insnbuf = xtensa_insnbuf_alloc (isa);
       while (frag != NULL)
        {
          if (frag->tc_frag_data.is_first_loop_insn)
            {
              int op_size;
-             int frag_addr;
+             addressT frag_addr;
              xtensa_format fmt;
 
              xtensa_format fmt;
 
-             xtensa_insnbuf_from_chars (isa, insnbuf, frag->fr_literal, 0);
+             xtensa_insnbuf_from_chars
+               (isa, insnbuf, (unsigned char *) frag->fr_literal, 0);
              fmt = xtensa_format_decode (isa, insnbuf);
              op_size = xtensa_format_length (isa, fmt);
              frag_addr = frag->fr_address % xtensa_fetch_width;
 
              fmt = xtensa_format_decode (isa, insnbuf);
              op_size = xtensa_format_length (isa, fmt);
              frag_addr = frag->fr_address % xtensa_fetch_width;
 
-             if (frag_addr + op_size > (signed) xtensa_fetch_width)
+             if (frag_addr + op_size > xtensa_fetch_width)
                as_warn_where (frag->fr_file, frag->fr_line,
                               _("unaligned loop: %d bytes at 0x%lx"),
                as_warn_where (frag->fr_file, frag->fr_line,
                               _("unaligned loop: %d bytes at 0x%lx"),
-                              op_size, frag->fr_address);
+                              op_size, (long) frag->fr_address);
            }
          frag = frag->fr_next;
        }
            }
          frag = frag->fr_next;
        }
@@ -4933,8 +4845,8 @@ xtensa_find_unaligned_loops (bfd *abfd ATTRIBUTE_UNUSED,
 }
 
 
 }
 
 
-static void
-xg_apply_tentative_value (fixS *fixP, valueT val)
+static int
+xg_apply_fix_value (fixS *fixP, valueT val)
 {
   xtensa_isa isa = xtensa_default_isa;
   static xtensa_insnbuf insnbuf = NULL;
 {
   xtensa_isa isa = xtensa_default_isa;
   static xtensa_insnbuf insnbuf = NULL;
@@ -4955,7 +4867,7 @@ xg_apply_tentative_value (fixS *fixP, valueT val)
       slotbuf = xtensa_insnbuf_alloc (isa);
     }
 
       slotbuf = xtensa_insnbuf_alloc (isa);
     }
 
-  xtensa_insnbuf_from_chars (isa, insnbuf, fixpos, 0);
+  xtensa_insnbuf_from_chars (isa, insnbuf, (unsigned char *) fixpos, 0);
   fmt = xtensa_format_decode (isa, insnbuf);
   if (fmt == XTENSA_UNDEFINED)
     as_fatal (_("undecodable fix"));
   fmt = xtensa_format_decode (isa, insnbuf);
   if (fmt == XTENSA_UNDEFINED)
     as_fatal (_("undecodable fix"));
@@ -4966,18 +4878,18 @@ xg_apply_tentative_value (fixS *fixP, valueT val)
 
   /* CONST16 immediates are not PC-relative, despite the fact that we
      reuse the normal PC-relative operand relocations for the low part
 
   /* CONST16 immediates are not PC-relative, despite the fact that we
      reuse the normal PC-relative operand relocations for the low part
-     of a CONST16 operand.  The code in tc_gen_reloc does not decode
-     the opcodes so it is more convenient to detect this special case
-     here.  */
+     of a CONST16 operand.  */
   if (opcode == xtensa_const16_opcode)
   if (opcode == xtensa_const16_opcode)
-    return;
+    return 0;
 
   xtensa_insnbuf_set_operand (slotbuf, fmt, slot, opcode,
                              get_relaxable_immed (opcode), val,
                              fixP->fx_file, fixP->fx_line);
 
   xtensa_format_set_slot (isa, fmt, slot, insnbuf, slotbuf);
 
   xtensa_insnbuf_set_operand (slotbuf, fmt, slot, opcode,
                              get_relaxable_immed (opcode), val,
                              fixP->fx_file, fixP->fx_line);
 
   xtensa_format_set_slot (isa, fmt, slot, insnbuf, slotbuf);
-  xtensa_insnbuf_to_chars (isa, insnbuf, fixpos, 0);
+  xtensa_insnbuf_to_chars (isa, insnbuf, (unsigned char *) fixpos, 0);
+
+  return 1;
 }
 
 \f
 }
 
 \f
@@ -5088,6 +5000,16 @@ xtensa_init_fix_data (fixS *x)
 void
 xtensa_frob_label (symbolS *sym)
 {
 void
 xtensa_frob_label (symbolS *sym)
 {
+  float freq;
+
+  if (cur_vinsn.inside_bundle)
+    {
+      as_bad (_("labels are not valid inside bundles"));
+      return;
+    }
+
+  freq = get_subseg_target_freq (now_seg, now_subseg);
+
   /* Since the label was already attached to a frag associated with the
      previous basic block, it now needs to be reset to the current frag.  */
   symbol_set_frag (sym, frag_now);
   /* Since the label was already attached to a frag associated with the
      previous basic block, it now needs to be reset to the current frag.  */
   symbol_set_frag (sym, frag_now);
@@ -5098,10 +5020,19 @@ xtensa_frob_label (symbolS *sym)
   else
     xtensa_add_insn_label (sym);
 
   else
     xtensa_add_insn_label (sym);
 
-  if (symbol_get_tc (sym)->is_loop_target
-      && (get_last_insn_flags (now_seg, now_subseg)
+  if (symbol_get_tc (sym)->is_loop_target)
+    {
+      if ((get_last_insn_flags (now_seg, now_subseg)
          & FLAG_IS_BAD_LOOPEND) != 0)
          & FLAG_IS_BAD_LOOPEND) != 0)
-    as_bad (_("invalid last instruction for a zero-overhead loop"));
+       as_bad (_("invalid last instruction for a zero-overhead loop"));
+
+      xtensa_set_frag_assembly_state (frag_now);
+      frag_var (rs_machine_dependent, 4, 4, RELAX_LOOP_END,
+               frag_now->fr_symbol, frag_now->fr_offset, NULL);
+
+      xtensa_set_frag_assembly_state (frag_now);
+      xtensa_move_labels (frag_now, 0, TRUE);
+    }
 
   /* No target aligning in the absolute section.  */
   if (now_seg != absolute_section
 
   /* No target aligning in the absolute section.  */
   if (now_seg != absolute_section
@@ -5109,26 +5040,10 @@ xtensa_frob_label (symbolS *sym)
       && !is_unaligned_label (sym)
       && !generating_literals)
     {
       && !is_unaligned_label (sym)
       && !generating_literals)
     {
-      float freq = get_subseg_target_freq (now_seg, now_subseg);
       xtensa_set_frag_assembly_state (frag_now);
 
       xtensa_set_frag_assembly_state (frag_now);
 
-      /* The only time this type of frag grows is when there is a
-        negatable branch that needs to be relaxed as the last
-        instruction in a zero-overhead loop.  Because alignment frags
-        are so common, marking them all as possibly growing four
-        bytes makes any worst-case analysis appear much worse than it
-        is.  So, we make fr_var not actually reflect the amount of
-        memory allocated at the end of this frag, but rather the
-        amount of memory this frag might grow.  The "4, 0" below
-        allocates four bytes at the end of the frag for room to grow
-        if we need to relax a loop end with a NOP.  Frags prior to
-        this one might grow to align this one, but the frag itself
-        won't grow unless it meets the condition above.  */
-
-#define RELAX_LOOP_END_BYTES 4
-
       frag_var (rs_machine_dependent,
       frag_var (rs_machine_dependent,
-               RELAX_LOOP_END_BYTES, (int) freq,
+               0, (int) freq,
                RELAX_DESIRE_ALIGN_IF_TARGET,
                frag_now->fr_symbol, frag_now->fr_offset, NULL);
       xtensa_set_frag_assembly_state (frag_now);
                RELAX_DESIRE_ALIGN_IF_TARGET,
                frag_now->fr_symbol, frag_now->fr_offset, NULL);
       xtensa_set_frag_assembly_state (frag_now);
@@ -5146,6 +5061,8 @@ xtensa_frob_label (symbolS *sym)
   /* Loops only go forward, so they can be identified here.  */
   if (symbol_get_tc (sym)->is_loop_target)
     symbol_get_frag (sym)->tc_frag_data.is_loop_target = TRUE;
   /* Loops only go forward, so they can be identified here.  */
   if (symbol_get_tc (sym)->is_loop_target)
     symbol_get_frag (sym)->tc_frag_data.is_loop_target = TRUE;
+
+  dwarf2_emit_label (sym);
 }
 
 
 }
 
 
@@ -5238,7 +5155,7 @@ void
 md_assemble (char *str)
 {
   xtensa_isa isa = xtensa_default_isa;
 md_assemble (char *str)
 {
   xtensa_isa isa = xtensa_default_isa;
-  char *opname;
+  char *opname, *file_name;
   unsigned opnamelen;
   bfd_boolean has_underbar = FALSE;
   char *arg_strings[MAX_INSN_ARGS];
   unsigned opnamelen;
   bfd_boolean has_underbar = FALSE;
   char *arg_strings[MAX_INSN_ARGS];
@@ -5299,11 +5216,6 @@ md_assemble (char *str)
       return;
     }
 
       return;
     }
 
-  /* Special case: The call instructions should be marked "specific opcode"
-     to keep them from expanding.  */
-  if (!use_longcalls () && is_direct_call_opcode (orig_insn.opcode))
-    orig_insn.is_specific_opcode = TRUE;
-
   /* Parse the arguments.  */
   if (parse_arguments (&orig_insn, num_args, arg_strings))
     {
   /* Parse the arguments.  */
   if (parse_arguments (&orig_insn, num_args, arg_strings))
     {
@@ -5332,28 +5244,20 @@ md_assemble (char *str)
       return;
     }
 
       return;
     }
 
-  dwarf2_where (&orig_insn.loc);
-  
+  /* A FLIX bundle may be spread across multiple input lines.  We want to
+     report the first such line in the debug information.  Record the line
+     number for each TInsn (assume the file name doesn't change), so the
+     first line can be found later.  */
+  as_where (&file_name, &orig_insn.linenum);
+
   xg_add_branch_and_loop_targets (&orig_insn);
 
   xg_add_branch_and_loop_targets (&orig_insn);
 
-  /* Special-case for "entry" instruction.  */
-  if (orig_insn.opcode == xtensa_entry_opcode)
+  /* Check that immediate value for ENTRY is >= 16.  */
+  if (orig_insn.opcode == xtensa_entry_opcode && orig_insn.ntok >= 3)
     {
     {
-      /* Check that the third opcode (#2) is >= 16.  */
-      if (orig_insn.ntok >= 3)
-       {
-         expressionS *exp = &orig_insn.tok[2];
-         switch (exp->X_op)
-           {
-           case O_constant:
-             if (exp->X_add_number < 16)
-               as_warn (_("entry instruction with stack decrement < 16"));
-             break;
-
-           default:
-             as_warn (_("entry instruction with non-constant decrement"));
-           }
-       }
+      expressionS *exp = &orig_insn.tok[2];
+      if (exp->X_op == O_constant && exp->X_add_number < 16)
+       as_warn (_("entry instruction with stack decrement < 16"));
     }
 
   /* Finish it off:
     }
 
   /* Finish it off:
@@ -5405,7 +5309,7 @@ xtensa_handle_align (fragS *fragP)
       int count;
       count = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
       if (count != 0)
       int count;
       count = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
       if (count != 0)
-       as_bad_where (fragP->fr_file, fragP->fr_line, 
+       as_bad_where (fragP->fr_file, fragP->fr_line,
                      _("unaligned entry instruction"));
     }
 }
                      _("unaligned entry instruction"));
     }
 }
@@ -5451,11 +5355,8 @@ md_pcrel_from (fixS *fixP)
   valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
   bfd_boolean alt_reloc;
 
   valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
   bfd_boolean alt_reloc;
 
-  if (fixP->fx_done)
-    return addr;
-
   if (fixP->fx_r_type == BFD_RELOC_XTENSA_ASM_EXPAND)
   if (fixP->fx_r_type == BFD_RELOC_XTENSA_ASM_EXPAND)
-    return addr;
+    return 0;
 
   if (!insnbuf)
     {
 
   if (!insnbuf)
     {
@@ -5464,7 +5365,7 @@ md_pcrel_from (fixS *fixP)
     }
 
   insn_p = &fixP->fx_frag->fr_literal[fixP->fx_where];
     }
 
   insn_p = &fixP->fx_frag->fr_literal[fixP->fx_where];
-  xtensa_insnbuf_from_chars (isa, insnbuf, insn_p, 0);
+  xtensa_insnbuf_from_chars (isa, insnbuf, (unsigned char *) insn_p, 0);
   fmt = xtensa_format_decode (isa, insnbuf);
 
   if (fmt == XTENSA_UNDEFINED)
   fmt = xtensa_format_decode (isa, insnbuf);
 
   if (fmt == XTENSA_UNDEFINED)
@@ -5476,14 +5377,15 @@ md_pcrel_from (fixS *fixP)
   xtensa_format_get_slot (isa, fmt, slot, insnbuf, slotbuf);
   opcode = xtensa_opcode_decode (isa, fmt, slot, slotbuf);
 
   xtensa_format_get_slot (isa, fmt, slot, insnbuf, slotbuf);
   opcode = xtensa_opcode_decode (isa, fmt, slot, slotbuf);
 
-  /* Check for "alternate" relocation (operand not specified).  */
+  /* Check for "alternate" relocations (operand not specified).  None
+     of the current uses for these are really PC-relative.  */
   if (alt_reloc || opcode == xtensa_const16_opcode)
     {
       if (opcode != xtensa_l32r_opcode
          && opcode != xtensa_const16_opcode)
        as_fatal (_("invalid relocation for '%s' instruction"),
                  xtensa_opcode_name (isa, opcode));
   if (alt_reloc || opcode == xtensa_const16_opcode)
     {
       if (opcode != xtensa_l32r_opcode
          && opcode != xtensa_const16_opcode)
        as_fatal (_("invalid relocation for '%s' instruction"),
                  xtensa_opcode_name (isa, opcode));
-      return addr;
+      return 0;
     }
 
   opnum = get_relaxable_immed (opcode);
     }
 
   opnum = get_relaxable_immed (opcode);
@@ -5495,7 +5397,7 @@ md_pcrel_from (fixS *fixP)
                    fixP->fx_line,
                    _("invalid relocation for operand %d of '%s'"),
                    opnum, xtensa_opcode_name (isa, opcode));
                    fixP->fx_line,
                    _("invalid relocation for operand %d of '%s'"),
                    opnum, xtensa_opcode_name (isa, opcode));
-      return addr;
+      return 0;
     }
   return 0 - opnd_value;
 }
     }
   return 0 - opnd_value;
 }
@@ -5507,7 +5409,8 @@ int
 xtensa_force_relocation (fixS *fix)
 {
   switch (fix->fx_r_type)
 xtensa_force_relocation (fixS *fix)
 {
   switch (fix->fx_r_type)
-   {
+    {
+    case BFD_RELOC_XTENSA_ASM_EXPAND:
     case BFD_RELOC_XTENSA_SLOT0_ALT:
     case BFD_RELOC_XTENSA_SLOT1_ALT:
     case BFD_RELOC_XTENSA_SLOT2_ALT:
     case BFD_RELOC_XTENSA_SLOT0_ALT:
     case BFD_RELOC_XTENSA_SLOT1_ALT:
     case BFD_RELOC_XTENSA_SLOT2_ALT:
@@ -5523,8 +5426,6 @@ xtensa_force_relocation (fixS *fix)
     case BFD_RELOC_XTENSA_SLOT12_ALT:
     case BFD_RELOC_XTENSA_SLOT13_ALT:
     case BFD_RELOC_XTENSA_SLOT14_ALT:
     case BFD_RELOC_XTENSA_SLOT12_ALT:
     case BFD_RELOC_XTENSA_SLOT13_ALT:
     case BFD_RELOC_XTENSA_SLOT14_ALT:
-    case BFD_RELOC_VTABLE_INHERIT:
-    case BFD_RELOC_VTABLE_ENTRY:
       return 1;
     default:
       break;
       return 1;
     default:
       break;
@@ -5538,6 +5439,33 @@ xtensa_force_relocation (fixS *fix)
 }
 
 
 }
 
 
+/* TC_VALIDATE_FIX_SUB hook */
+
+int
+xtensa_validate_fix_sub (fixS *fix)
+{
+  segT add_symbol_segment, sub_symbol_segment;
+
+  /* The difference of two symbols should be resolved by the assembler when
+     linkrelax is not set.  If the linker may relax the section containing
+     the symbols, then an Xtensa DIFF relocation must be generated so that
+     the linker knows to adjust the difference value.  */
+  if (!linkrelax || fix->fx_addsy == NULL)
+    return 0;
+
+  /* Make sure both symbols are in the same segment, and that segment is
+     "normal" and relaxable.  If the segment is not "normal", then the
+     fix is not valid.  If the segment is not "relaxable", then the fix
+     should have been handled earlier.  */
+  add_symbol_segment = S_GET_SEGMENT (fix->fx_addsy);
+  if (! SEG_NORMAL (add_symbol_segment) ||
+      ! relaxable_section (add_symbol_segment))
+    return 0;
+  sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
+  return (sub_symbol_segment == add_symbol_segment);
+}
+
+
 /* NO_PSEUDO_DOT hook */
 
 /* This function has nothing to do with pseudo dots, but this is the
 /* NO_PSEUDO_DOT hook */
 
 /* This function has nothing to do with pseudo dots, but this is the
@@ -5585,59 +5513,142 @@ xtensa_fix_adjustable (fixS *fixP)
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
 
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
 
-  if (fixP->fx_addsy
-      && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
-    return 0;
-
-#if 0
-  /* We may someday want to enable this code to preserve relocations for
-     non-PC-relative fixes, possibly under control of a PIC flag.  */
-  return (fixP->fx_pcrel
-         || (fixP->fx_subsy != NULL
-             && (S_GET_SEGMENT (fixP->fx_subsy)
-                 == S_GET_SEGMENT (fixP->fx_addsy)))
-         || S_IS_LOCAL (fixP->fx_addsy));
-#else
   return 1;
   return 1;
-#endif
 }
 
 
 void
 }
 
 
 void
-md_apply_fix3 (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
+md_apply_fix (fixS *fixP, valueT *valP, segT seg)
 {
 {
-  if (fixP->fx_pcrel == 0 && fixP->fx_addsy == 0)
-    {
-      char *const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
+  char *const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
+  valueT val = 0;
 
 
-      switch (fixP->fx_r_type)
+  /* Subtracted symbols are only allowed for a few relocation types, and
+     unless linkrelax is enabled, they should not make it to this point.  */
+  if (fixP->fx_subsy && !(linkrelax && (fixP->fx_r_type == BFD_RELOC_32
+                                       || fixP->fx_r_type == BFD_RELOC_16
+                                       || fixP->fx_r_type == BFD_RELOC_8)))
+    as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
+
+  switch (fixP->fx_r_type)
+    {
+    case BFD_RELOC_32:
+    case BFD_RELOC_16:
+    case BFD_RELOC_8:
+      if (fixP->fx_subsy)
        {
        {
-       case BFD_RELOC_XTENSA_ASM_EXPAND:
-         fixP->fx_done = 1;
-         break;
+         switch (fixP->fx_r_type)
+           {
+           case BFD_RELOC_8:
+             fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF8;
+             break;
+           case BFD_RELOC_16:
+             fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF16;
+             break;
+           case BFD_RELOC_32:
+             fixP->fx_r_type = BFD_RELOC_XTENSA_DIFF32;
+             break;
+           default:
+             break;
+           }
 
 
-       case BFD_RELOC_XTENSA_ASM_SIMPLIFY:
-         as_bad (_("unhandled local relocation fix %s"),
-                 bfd_get_reloc_code_name (fixP->fx_r_type));
-         break;
+         /* An offset is only allowed when it results from adjusting a
+            local symbol into a section-relative offset.  If the offset
+            came from the original expression, tc_fix_adjustable will have
+            prevented the fix from being converted to a section-relative
+            form so that we can flag the error here.  */
+         if (fixP->fx_offset != 0 && !symbol_section_p (fixP->fx_addsy))
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("cannot represent subtraction with an offset"));
 
 
-       case BFD_RELOC_32:
-       case BFD_RELOC_16:
-       case BFD_RELOC_8:
-         /* The only one we support that isn't an instruction field.  */
-         md_number_to_chars (fixpos, *valP, fixP->fx_size);
+         val = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
+                - S_GET_VALUE (fixP->fx_subsy));
+
+         /* The difference value gets written out, and the DIFF reloc
+            identifies the address of the subtracted symbol (i.e., the one
+            with the lowest address).  */
+         *valP = val;
+         fixP->fx_offset -= val;
+         fixP->fx_subsy = NULL;
+       }
+      else if (! fixP->fx_addsy)
+       {
+         val = *valP;
          fixP->fx_done = 1;
          fixP->fx_done = 1;
-         break;
+       }
+      /* fall through */
 
 
-       case BFD_RELOC_VTABLE_INHERIT:
-       case BFD_RELOC_VTABLE_ENTRY:
-         fixP->fx_done = 0;
-         break;
+    case BFD_RELOC_XTENSA_PLT:
+      md_number_to_chars (fixpos, val, fixP->fx_size);
+      fixP->fx_no_overflow = 0; /* Use the standard overflow check.  */
+      break;
 
 
-       default:
-         as_bad (_("unhandled local relocation fix %s"),
-                 bfd_get_reloc_code_name (fixP->fx_r_type));
+    case BFD_RELOC_XTENSA_SLOT0_OP:
+    case BFD_RELOC_XTENSA_SLOT1_OP:
+    case BFD_RELOC_XTENSA_SLOT2_OP:
+    case BFD_RELOC_XTENSA_SLOT3_OP:
+    case BFD_RELOC_XTENSA_SLOT4_OP:
+    case BFD_RELOC_XTENSA_SLOT5_OP:
+    case BFD_RELOC_XTENSA_SLOT6_OP:
+    case BFD_RELOC_XTENSA_SLOT7_OP:
+    case BFD_RELOC_XTENSA_SLOT8_OP:
+    case BFD_RELOC_XTENSA_SLOT9_OP:
+    case BFD_RELOC_XTENSA_SLOT10_OP:
+    case BFD_RELOC_XTENSA_SLOT11_OP:
+    case BFD_RELOC_XTENSA_SLOT12_OP:
+    case BFD_RELOC_XTENSA_SLOT13_OP:
+    case BFD_RELOC_XTENSA_SLOT14_OP:
+      if (linkrelax)
+       {
+         /* Write the tentative value of a PC-relative relocation to a
+            local symbol into the instruction.  The value will be ignored
+            by the linker, and it makes the object file disassembly
+            readable when all branch targets are encoded in relocations.  */
+
+         assert (fixP->fx_addsy);
+         if (S_GET_SEGMENT (fixP->fx_addsy) == seg && !fixP->fx_plt
+             && !S_FORCE_RELOC (fixP->fx_addsy, 1))
+           {
+             val = (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset
+                    - md_pcrel_from (fixP));
+             (void) xg_apply_fix_value (fixP, val);
+           }
+       }
+      else if (! fixP->fx_addsy)
+       {
+         val = *valP;
+         if (xg_apply_fix_value (fixP, val))
+           fixP->fx_done = 1;
        }
        }
+      break;
+
+    case BFD_RELOC_XTENSA_ASM_EXPAND:
+    case BFD_RELOC_XTENSA_SLOT0_ALT:
+    case BFD_RELOC_XTENSA_SLOT1_ALT:
+    case BFD_RELOC_XTENSA_SLOT2_ALT:
+    case BFD_RELOC_XTENSA_SLOT3_ALT:
+    case BFD_RELOC_XTENSA_SLOT4_ALT:
+    case BFD_RELOC_XTENSA_SLOT5_ALT:
+    case BFD_RELOC_XTENSA_SLOT6_ALT:
+    case BFD_RELOC_XTENSA_SLOT7_ALT:
+    case BFD_RELOC_XTENSA_SLOT8_ALT:
+    case BFD_RELOC_XTENSA_SLOT9_ALT:
+    case BFD_RELOC_XTENSA_SLOT10_ALT:
+    case BFD_RELOC_XTENSA_SLOT11_ALT:
+    case BFD_RELOC_XTENSA_SLOT12_ALT:
+    case BFD_RELOC_XTENSA_SLOT13_ALT:
+    case BFD_RELOC_XTENSA_SLOT14_ALT:
+      /* These all need to be resolved at link-time.  Do nothing now.  */
+      break;
+
+    case BFD_RELOC_VTABLE_INHERIT:
+    case BFD_RELOC_VTABLE_ENTRY:
+      fixP->fx_done = 0;
+      break;
+
+    default:
+      as_bad (_("unhandled local relocation fix %s"),
+             bfd_get_reloc_code_name (fixP->fx_r_type));
     }
 }
 
     }
 }
 
@@ -5696,10 +5707,9 @@ md_estimate_size_before_relax (fragS *fragP, segT seg ATTRIBUTE_UNUSED)
    format.  */
 
 arelent *
    format.  */
 
 arelent *
-tc_gen_reloc (asection *section, fixS *fixp)
+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
 {
   arelent *reloc;
 {
   arelent *reloc;
-  bfd_boolean apply_tentative_value = FALSE;
 
   reloc = (arelent *) xmalloc (sizeof (arelent));
   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
 
   reloc = (arelent *) xmalloc (sizeof (arelent));
   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
@@ -5710,128 +5720,7 @@ tc_gen_reloc (asection *section, fixS *fixp)
      They'd better have been fully resolved by this point.  */
   assert ((int) fixp->fx_r_type > 0);
 
      They'd better have been fully resolved by this point.  */
   assert ((int) fixp->fx_r_type > 0);
 
-  if (linkrelax && fixp->fx_subsy
-      && (fixp->fx_r_type == BFD_RELOC_8
-         || fixp->fx_r_type == BFD_RELOC_16
-         || fixp->fx_r_type == BFD_RELOC_32))
-    {
-      int diff_size = 0;
-      bfd_vma diff_value, diff_mask = 0;
-
-      switch (fixp->fx_r_type)
-       {
-       case BFD_RELOC_8:
-         fixp->fx_r_type = BFD_RELOC_XTENSA_DIFF8;
-         diff_size = 1;
-         diff_mask = 0xff;
-         break;
-       case BFD_RELOC_16:
-         fixp->fx_r_type = BFD_RELOC_XTENSA_DIFF16;
-         diff_size = 2;
-         diff_mask = 0xffff;
-         break;
-       case BFD_RELOC_32:
-         fixp->fx_r_type = BFD_RELOC_XTENSA_DIFF32;
-         diff_size = 4;
-         diff_mask = 0xffffffff;
-         break;
-       default:
-         break;
-       }
-
-      /* An offset is only allowed when it results from adjusting a local
-        symbol into a section-relative offset.  If the offset came from the
-        original expression, tc_fix_adjustable will have prevented the fix
-        from being converted to a section-relative form so that we can flag
-        the error here.  */
-      if (fixp->fx_offset != 0 && !symbol_section_p (fixp->fx_addsy))
-       {
-         as_bad_where (fixp->fx_file, fixp->fx_line,
-                       _("cannot represent subtraction with an offset"));
-         free (reloc->sym_ptr_ptr);
-         free (reloc);
-         return NULL;
-       }
-
-      assert (S_GET_SEGMENT (fixp->fx_addsy)
-             == S_GET_SEGMENT (fixp->fx_subsy));
-
-      diff_value = (S_GET_VALUE (fixp->fx_addsy) + fixp->fx_offset
-                   - S_GET_VALUE (fixp->fx_subsy));
-
-      /* Check for overflow.  */
-      if ((diff_value & ~diff_mask) != 0)
-       {
-         as_bad_where (fixp->fx_file, fixp->fx_line,
-                       _("value of %ld too large"), diff_value);
-         free (reloc->sym_ptr_ptr);
-         free (reloc);
-         return NULL;
-       }
-
-      md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
-                         diff_value, diff_size);
-      reloc->addend = fixp->fx_offset - diff_value;
-    }
-  else
-    {
-      reloc->addend = fixp->fx_offset;
-
-      switch (fixp->fx_r_type)
-       {
-       case BFD_RELOC_XTENSA_SLOT0_OP:
-       case BFD_RELOC_XTENSA_SLOT1_OP:
-       case BFD_RELOC_XTENSA_SLOT2_OP:
-       case BFD_RELOC_XTENSA_SLOT3_OP:
-       case BFD_RELOC_XTENSA_SLOT4_OP:
-       case BFD_RELOC_XTENSA_SLOT5_OP:
-       case BFD_RELOC_XTENSA_SLOT6_OP:
-       case BFD_RELOC_XTENSA_SLOT7_OP:
-       case BFD_RELOC_XTENSA_SLOT8_OP:
-       case BFD_RELOC_XTENSA_SLOT9_OP:
-       case BFD_RELOC_XTENSA_SLOT10_OP:
-       case BFD_RELOC_XTENSA_SLOT11_OP:
-       case BFD_RELOC_XTENSA_SLOT12_OP:
-       case BFD_RELOC_XTENSA_SLOT13_OP:
-       case BFD_RELOC_XTENSA_SLOT14_OP:
-         /* As a special case, the immediate value for a CONST16 opcode
-            should not be applied, since this kind of relocation is
-            handled specially for CONST16 and is not really PC-relative.
-            Rather than decode the opcode here, just wait and handle it
-            in xg_apply_tentative_value.  */
-         apply_tentative_value = TRUE;
-         break;
-
-       case BFD_RELOC_XTENSA_SLOT0_ALT:
-       case BFD_RELOC_XTENSA_SLOT1_ALT:
-       case BFD_RELOC_XTENSA_SLOT2_ALT:
-       case BFD_RELOC_XTENSA_SLOT3_ALT:
-       case BFD_RELOC_XTENSA_SLOT4_ALT:
-       case BFD_RELOC_XTENSA_SLOT5_ALT:
-       case BFD_RELOC_XTENSA_SLOT6_ALT:
-       case BFD_RELOC_XTENSA_SLOT7_ALT:
-       case BFD_RELOC_XTENSA_SLOT8_ALT:
-       case BFD_RELOC_XTENSA_SLOT9_ALT:
-       case BFD_RELOC_XTENSA_SLOT10_ALT:
-       case BFD_RELOC_XTENSA_SLOT11_ALT:
-       case BFD_RELOC_XTENSA_SLOT12_ALT:
-       case BFD_RELOC_XTENSA_SLOT13_ALT:
-       case BFD_RELOC_XTENSA_SLOT14_ALT:
-       case BFD_RELOC_XTENSA_ASM_EXPAND:
-       case BFD_RELOC_32:
-       case BFD_RELOC_XTENSA_PLT:
-       case BFD_RELOC_VTABLE_INHERIT:
-       case BFD_RELOC_VTABLE_ENTRY:
-         break;
-
-       case BFD_RELOC_XTENSA_ASM_SIMPLIFY:
-         as_warn (_("emitting simplification relocation"));
-         break;
-
-       default:
-         as_warn (_("emitting unknown relocation"));
-       }
-    }
+  reloc->addend = fixp->fx_offset;
 
   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
   if (reloc->howto == NULL)
 
   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
   if (reloc->howto == NULL)
@@ -5848,35 +5737,17 @@ tc_gen_reloc (asection *section, fixS *fixp)
     as_fatal (_("internal error? cannot generate `%s' relocation"),
              bfd_get_reloc_code_name (fixp->fx_r_type));
 
     as_fatal (_("internal error? cannot generate `%s' relocation"),
              bfd_get_reloc_code_name (fixp->fx_r_type));
 
-  /* Write the tentative value of a PC-relative relocation to a local symbol
-     into the instruction.  The value will be ignored by the linker, and it
-     makes the object file disassembly readable when the linkrelax flag is
-     set and all branch targets are encoded in relocations.  */
-
-  if (linkrelax && apply_tentative_value && fixp->fx_pcrel)
-    {
-      valueT val;
-      assert (fixp->fx_addsy);
-      if (S_GET_SEGMENT (fixp->fx_addsy) == section && !fixp->fx_plt
-         && !S_FORCE_RELOC (fixp->fx_addsy, 1))
-       {
-         val = (S_GET_VALUE (fixp->fx_addsy) + fixp->fx_offset
-                - md_pcrel_from (fixp));
-         xg_apply_tentative_value (fixp, val);
-       }
-    }
-
-  return reloc;
-}
+  return reloc;
+}
 
 \f
 /* Checks for resource conflicts between instructions.  */
 
 
 \f
 /* Checks for resource conflicts between instructions.  */
 
-/* The func unit stuff could be implemented as bit-vectors rather 
-   than the iterative approach here.  If it ends up being too 
+/* The func unit stuff could be implemented as bit-vectors rather
+   than the iterative approach here.  If it ends up being too
    slow, we will switch it.  */
 
    slow, we will switch it.  */
 
-resource_table * 
+resource_table *
 new_resource_table (void *data,
                    int cycles,
                    int nu,
 new_resource_table (void *data,
                    int cycles,
                    int nu,
@@ -5896,15 +5767,15 @@ new_resource_table (void *data,
   rt->opcode_unit_use = ouuf;
   rt->opcode_unit_stage = ousf;
 
   rt->opcode_unit_use = ouuf;
   rt->opcode_unit_stage = ousf;
 
-  rt->units = (char **) xcalloc (cycles, sizeof (char *));
+  rt->units = (unsigned char **) xcalloc (cycles, sizeof (unsigned char *));
   for (i = 0; i < cycles; i++)
   for (i = 0; i < cycles; i++)
-    rt->units[i] = (char *) xcalloc (nu, sizeof (char));
+    rt->units[i] = (unsigned char *) xcalloc (nu, sizeof (unsigned char));
 
   return rt;
 }
 
 
 
   return rt;
 }
 
 
-void 
+void
 clear_resource_table (resource_table *rt)
 {
   int i, j;
 clear_resource_table (resource_table *rt)
 {
   int i, j;
@@ -5916,7 +5787,7 @@ clear_resource_table (resource_table *rt)
 
 /* We never shrink it, just fake it into thinking so.  */
 
 
 /* We never shrink it, just fake it into thinking so.  */
 
-void 
+void
 resize_resource_table (resource_table *rt, int cycles)
 {
   int i, old_cycles;
 resize_resource_table (resource_table *rt, int cycles)
 {
   int i, old_cycles;
@@ -5928,21 +5799,23 @@ resize_resource_table (resource_table *rt, int cycles)
   old_cycles = rt->allocated_cycles;
   rt->allocated_cycles = cycles;
 
   old_cycles = rt->allocated_cycles;
   rt->allocated_cycles = cycles;
 
-  rt->units = xrealloc (rt->units, sizeof (char *) * rt->allocated_cycles);
+  rt->units = xrealloc (rt->units,
+                       rt->allocated_cycles * sizeof (unsigned char *));
   for (i = 0; i < old_cycles; i++)
   for (i = 0; i < old_cycles; i++)
-    rt->units[i] = xrealloc (rt->units[i], sizeof (char) * rt->num_units);
+    rt->units[i] = xrealloc (rt->units[i],
+                            rt->num_units * sizeof (unsigned char));
   for (i = old_cycles; i < cycles; i++)
   for (i = old_cycles; i < cycles; i++)
-    rt->units[i] = xcalloc (rt->num_units, sizeof (char));
+    rt->units[i] = xcalloc (rt->num_units, sizeof (unsigned char));
 }
 
 
 }
 
 
-bfd_boolean 
+bfd_boolean
 resources_available (resource_table *rt, xtensa_opcode opcode, int cycle)
 {
   int i;
   int uses = (rt->opcode_num_units) (rt->data, opcode);
 
 resources_available (resource_table *rt, xtensa_opcode opcode, int cycle)
 {
   int i;
   int uses = (rt->opcode_num_units) (rt->data, opcode);
 
-  for (i = 0; i < uses; i++) 
+  for (i = 0; i < uses; i++)
     {
       xtensa_funcUnit unit = (rt->opcode_unit_use) (rt->data, opcode, i);
       int stage = (rt->opcode_unit_stage) (rt->data, opcode, i);
     {
       xtensa_funcUnit unit = (rt->opcode_unit_use) (rt->data, opcode, i);
       int stage = (rt->opcode_unit_stage) (rt->data, opcode, i);
@@ -5953,20 +5826,20 @@ resources_available (resource_table *rt, xtensa_opcode opcode, int cycle)
     }
   return TRUE;
 }
     }
   return TRUE;
 }
-     
 
 
-void 
+
+void
 reserve_resources (resource_table *rt, xtensa_opcode opcode, int cycle)
 {
   int i;
   int uses = (rt->opcode_num_units) (rt->data, opcode);
 
 reserve_resources (resource_table *rt, xtensa_opcode opcode, int cycle)
 {
   int i;
   int uses = (rt->opcode_num_units) (rt->data, opcode);
 
-  for (i = 0; i < uses; i++) 
+  for (i = 0; i < uses; i++)
     {
       xtensa_funcUnit unit = (rt->opcode_unit_use) (rt->data, opcode, i);
       int stage = (rt->opcode_unit_stage) (rt->data, opcode, i);
     {
       xtensa_funcUnit unit = (rt->opcode_unit_use) (rt->data, opcode, i);
       int stage = (rt->opcode_unit_stage) (rt->data, opcode, i);
-      /* Note that this allows resources to be oversubscribed.  That's 
-        essential to the way the optional scheduler works. 
+      /* Note that this allows resources to be oversubscribed.  That's
+        essential to the way the optional scheduler works.
         resources_available reports when a resource is over-subscribed,
         so it's easy to tell.  */
       rt->units[stage + cycle][unit]++;
         resources_available reports when a resource is over-subscribed,
         so it's easy to tell.  */
       rt->units[stage + cycle][unit]++;
@@ -5974,34 +5847,34 @@ reserve_resources (resource_table *rt, xtensa_opcode opcode, int cycle)
 }
 
 
 }
 
 
-void 
+void
 release_resources (resource_table *rt, xtensa_opcode opcode, int cycle)
 {
   int i;
   int uses = (rt->opcode_num_units) (rt->data, opcode);
 
 release_resources (resource_table *rt, xtensa_opcode opcode, int cycle)
 {
   int i;
   int uses = (rt->opcode_num_units) (rt->data, opcode);
 
-  for (i = 0; i < uses; i++) 
+  for (i = 0; i < uses; i++)
     {
       xtensa_funcUnit unit = (rt->opcode_unit_use) (rt->data, opcode, i);
       int stage = (rt->opcode_unit_stage) (rt->data, opcode, i);
     {
       xtensa_funcUnit unit = (rt->opcode_unit_use) (rt->data, opcode, i);
       int stage = (rt->opcode_unit_stage) (rt->data, opcode, i);
+      assert (rt->units[stage + cycle][unit] > 0);
       rt->units[stage + cycle][unit]--;
       rt->units[stage + cycle][unit]--;
-      assert (rt->units[stage + cycle][unit] >= 0);
     }
 }
     }
 }
-     
+
 
 /* Wrapper functions make parameterized resource reservation
    more convenient.  */
 
 
 /* Wrapper functions make parameterized resource reservation
    more convenient.  */
 
-int 
+int
 opcode_funcUnit_use_unit (void *data, xtensa_opcode opcode, int idx)
 {
   xtensa_funcUnit_use *use = xtensa_opcode_funcUnit_use (data, opcode, idx);
 opcode_funcUnit_use_unit (void *data, xtensa_opcode opcode, int idx)
 {
   xtensa_funcUnit_use *use = xtensa_opcode_funcUnit_use (data, opcode, idx);
-  return use->unit;  
+  return use->unit;
 }
 
 
 }
 
 
-int 
+int
 opcode_funcUnit_use_stage (void *data, xtensa_opcode opcode, int idx)
 {
   xtensa_funcUnit_use *use = xtensa_opcode_funcUnit_use (data, opcode, idx);
 opcode_funcUnit_use_stage (void *data, xtensa_opcode opcode, int idx)
 {
   xtensa_funcUnit_use *use = xtensa_opcode_funcUnit_use (data, opcode, idx);
@@ -6011,9 +5884,9 @@ opcode_funcUnit_use_stage (void *data, xtensa_opcode opcode, int idx)
 
 /* Note that this function does not check issue constraints, but
    solely whether the hardware is available to execute the given
 
 /* Note that this function does not check issue constraints, but
    solely whether the hardware is available to execute the given
-   instructions together.  It also doesn't check if the tinsns 
+   instructions together.  It also doesn't check if the tinsns
    write the same state, or access the same tieports.  That is
    write the same state, or access the same tieports.  That is
-   checked by check_t1_t2_read_write.  */
+   checked by check_t1_t2_reads_and_writes.  */
 
 static bfd_boolean
 resources_conflict (vliw_insn *vinsn)
 
 static bfd_boolean
 resources_conflict (vliw_insn *vinsn)
@@ -6025,7 +5898,7 @@ resources_conflict (vliw_insn *vinsn)
   if (vinsn->num_slots == 1)
     return FALSE;
 
   if (vinsn->num_slots == 1)
     return FALSE;
 
-  if (rt == NULL) 
+  if (rt == NULL)
     {
       xtensa_isa isa = xtensa_default_isa;
       rt = new_resource_table
     {
       xtensa_isa isa = xtensa_default_isa;
       rt = new_resource_table
@@ -6054,7 +5927,6 @@ resources_conflict (vliw_insn *vinsn)
 
 static bfd_boolean find_vinsn_conflicts (vliw_insn *);
 static xtensa_format xg_find_narrowest_format (vliw_insn *);
 
 static bfd_boolean find_vinsn_conflicts (vliw_insn *);
 static xtensa_format xg_find_narrowest_format (vliw_insn *);
-static void bundle_single_op (TInsn *);
 static void xg_assemble_vliw_tokens (vliw_insn *);
 
 
 static void xg_assemble_vliw_tokens (vliw_insn *);
 
 
@@ -6066,10 +5938,13 @@ finish_vinsn (vliw_insn *vinsn)
   IStack slotstack;
   int i;
   char *file_name;
   IStack slotstack;
   int i;
   char *file_name;
-  int line;
+  unsigned line;
 
   if (find_vinsn_conflicts (vinsn))
 
   if (find_vinsn_conflicts (vinsn))
-    return;
+    {
+      xg_clear_vinsn (vinsn);
+      return;
+    }
 
   /* First, find a format that works.  */
   if (vinsn->format == XTENSA_UNDEFINED)
 
   /* First, find a format that works.  */
   if (vinsn->format == XTENSA_UNDEFINED)
@@ -6101,7 +5976,7 @@ finish_vinsn (vliw_insn *vinsn)
       return;
     }
 
       return;
     }
 
-  if (resources_conflict (vinsn)) 
+  if (resources_conflict (vinsn))
     {
       as_where (&file_name, &line);
       as_bad_where (file_name, line, _("illegal resource usage in bundle"));
     {
       as_where (&file_name, &line);
       as_bad_where (file_name, line, _("illegal resource usage in bundle"));
@@ -6151,7 +6026,7 @@ finish_vinsn (vliw_insn *vinsn)
              return;
            }
 
              return;
            }
 
-         for (j = 0; j < slotstack.ninsn - 1; j++)
+         for (j = 0; j < slotstack.ninsn; j++)
            {
              TInsn *insn = &slotstack.insn[j];
              if (insn->insn_type == ITYPE_LITERAL)
            {
              TInsn *insn = &slotstack.insn[j];
              if (insn->insn_type == ITYPE_LITERAL)
@@ -6161,9 +6036,11 @@ finish_vinsn (vliw_insn *vinsn)
                }
              else
                {
                }
              else
                {
+                 assert (insn->insn_type == ITYPE_INSN);
                  if (lit_sym)
                    xg_resolve_literals (insn, lit_sym);
                  if (lit_sym)
                    xg_resolve_literals (insn, lit_sym);
-                 emit_single_op (insn);
+                 if (j != slotstack.ninsn - 1)
+                   emit_single_op (insn);
                }
            }
 
                }
            }
 
@@ -6177,11 +6054,11 @@ finish_vinsn (vliw_insn *vinsn)
                }
              else
                {
                }
              else
                {
-                 bundle_single_op (&slotstack.insn[slotstack.ninsn - 1]);
+                 emit_single_op (&slotstack.insn[slotstack.ninsn - 1]);
                  if (vinsn->format == XTENSA_UNDEFINED)
                    vinsn->slots[i].opcode = xtensa_nop_opcode;
                  else
                  if (vinsn->format == XTENSA_UNDEFINED)
                    vinsn->slots[i].opcode = xtensa_nop_opcode;
                  else
-                   vinsn->slots[i].opcode 
+                   vinsn->slots[i].opcode
                      = xtensa_format_slot_nop_opcode (xtensa_default_isa,
                                                       vinsn->format, i);
 
                      = xtensa_format_slot_nop_opcode (xtensa_default_isa,
                                                       vinsn->format, i);
 
@@ -6197,7 +6074,7 @@ finish_vinsn (vliw_insn *vinsn)
     }
 
   /* Now check resource conflicts on the modified bundle.  */
     }
 
   /* Now check resource conflicts on the modified bundle.  */
-  if (resources_conflict (vinsn)) 
+  if (resources_conflict (vinsn))
     {
       as_where (&file_name, &line);
       as_bad_where (file_name, line, _("illegal resource usage in bundle"));
     {
       as_where (&file_name, &line);
       as_bad_where (file_name, line, _("illegal resource usage in bundle"));
@@ -6297,12 +6174,12 @@ find_vinsn_conflicts (vliw_insn *vinsn)
                          xtensa_opcode_name (isa, op2->opcode), j);
                  return TRUE;
                case 'e':
                          xtensa_opcode_name (isa, op2->opcode), j);
                  return TRUE;
                case 'e':
-                 as_bad (_("opcodes '%s' (slot %d) and '%s' (slot %d) write the same queue"),
+                 as_bad (_("opcodes '%s' (slot %d) and '%s' (slot %d) write the same port"),
                          xtensa_opcode_name (isa, op1->opcode), i,
                          xtensa_opcode_name (isa, op2->opcode), j);
                  return TRUE;
                case 'f':
                          xtensa_opcode_name (isa, op1->opcode), i,
                          xtensa_opcode_name (isa, op2->opcode), j);
                  return TRUE;
                case 'f':
-                 as_bad (_("opcodes '%s' (slot %d) and '%s' (slot %d) both have volatile queue accesses"),
+                 as_bad (_("opcodes '%s' (slot %d) and '%s' (slot %d) both have volatile port accesses"),
                          xtensa_opcode_name (isa, op1->opcode), i,
                          xtensa_opcode_name (isa, op2->opcode), j);
                  return TRUE;
                          xtensa_opcode_name (isa, op1->opcode), i,
                          xtensa_opcode_name (isa, op2->opcode), j);
                  return TRUE;
@@ -6326,17 +6203,17 @@ find_vinsn_conflicts (vliw_insn *vinsn)
 }
 
 
 }
 
 
-/* Check how the result registers of t1 and t2 relate.
+/* Check how the state used by t1 and t2 relate.
    Cases found are:
 
    case A: t1 reads a register t2 writes (an antidependency within a bundle)
    case B: no relationship between what is read and written (both could
            read the same reg though)
    Cases found are:
 
    case A: t1 reads a register t2 writes (an antidependency within a bundle)
    case B: no relationship between what is read and written (both could
            read the same reg though)
-   case C: t1 writes a register t2 writes (a register conflict within a 
+   case C: t1 writes a register t2 writes (a register conflict within a
            bundle)
    case D: t1 writes a state that t2 also writes
    case E: t1 writes a tie queue that t2 also writes
            bundle)
    case D: t1 writes a state that t2 also writes
    case E: t1 writes a tie queue that t2 also writes
-   case F: two volatile queue writes
+   case F: two volatile queue accesses
 */
 
 static char
 */
 
 static char
@@ -6432,7 +6309,7 @@ check_t1_t2_reads_and_writes (TInsn *t1, TInsn *t2)
        {
          xtensa_state t1_so = xtensa_stateOperand_state (isa, t1->opcode, i);
          t1_inout = xtensa_stateOperand_inout (isa, t1->opcode, i);
        {
          xtensa_state t1_so = xtensa_stateOperand_state (isa, t1->opcode, i);
          t1_inout = xtensa_stateOperand_inout (isa, t1->opcode, i);
-         if (t1_so != t2_so) 
+         if (t1_so != t2_so)
            continue;
 
          if (t2_inout == 'i' && (t1_inout == 'm' || t1_inout == 'o'))
            continue;
 
          if (t2_inout == 'i' && (t1_inout == 'm' || t1_inout == 'o'))
@@ -6440,61 +6317,64 @@ check_t1_t2_reads_and_writes (TInsn *t1, TInsn *t2)
              conflict = 'a';
              continue;
            }
              conflict = 'a';
              continue;
            }
-         
+
          if (t1_inout == 'i' && (t2_inout == 'm' || t2_inout == 'o'))
            {
              conflict = 'a';
              continue;
            }
          if (t1_inout == 'i' && (t2_inout == 'm' || t2_inout == 'o'))
            {
              conflict = 'a';
              continue;
            }
-         
+
          if (t1_inout != 'i' && t2_inout != 'i')
            return 'd';
          if (t1_inout != 'i' && t2_inout != 'i')
            return 'd';
-       }      
+       }
     }
 
   /* Check tieports.  */
   t1_interfaces = xtensa_opcode_num_interfaceOperands (isa, t1->opcode);
   t2_interfaces = xtensa_opcode_num_interfaceOperands (isa, t2->opcode);
     }
 
   /* Check tieports.  */
   t1_interfaces = xtensa_opcode_num_interfaceOperands (isa, t1->opcode);
   t2_interfaces = xtensa_opcode_num_interfaceOperands (isa, t2->opcode);
-  for (j = 0; j < t2_interfaces; j++) 
+  for (j = 0; j < t2_interfaces; j++)
     {
       xtensa_interface t2_int
        = xtensa_interfaceOperand_interface (isa, t2->opcode, j);
     {
       xtensa_interface t2_int
        = xtensa_interfaceOperand_interface (isa, t2->opcode, j);
-      t2_inout = xtensa_interface_inout (isa, j);
-      if (xtensa_interface_has_side_effect (isa, t2_int) == 1 
-         && t2_inout != 'i')
+      int t2_class = xtensa_interface_class_id (isa, t2_int);
+
+      t2_inout = xtensa_interface_inout (isa, t2_int);
+      if (xtensa_interface_has_side_effect (isa, t2_int) == 1)
        t2_volatile = TRUE;
        t2_volatile = TRUE;
+
       for (i = 0; i < t1_interfaces; i++)
        {
          xtensa_interface t1_int
            = xtensa_interfaceOperand_interface (isa, t1->opcode, j);
       for (i = 0; i < t1_interfaces; i++)
        {
          xtensa_interface t1_int
            = xtensa_interfaceOperand_interface (isa, t1->opcode, j);
-         t1_inout = xtensa_interface_inout (isa, i);
-         if (xtensa_interface_has_side_effect (isa, t1_int) == 1 
-             && t1_inout != 'i')
+         int t1_class = xtensa_interface_class_id (isa, t1_int);
+
+         t1_inout = xtensa_interface_inout (isa, t1_int);
+         if (xtensa_interface_has_side_effect (isa, t1_int) == 1)
            t1_volatile = TRUE;
            t1_volatile = TRUE;
-         
+
+         if (t1_volatile && t2_volatile && (t1_class == t2_class))
+           return 'f';
+
          if (t1_int != t2_int)
            continue;
          if (t1_int != t2_int)
            continue;
-         
+
          if (t2_inout == 'i' && t1_inout == 'o')
            {
              conflict = 'a';
              continue;
            }
          if (t2_inout == 'i' && t1_inout == 'o')
            {
              conflict = 'a';
              continue;
            }
-         
+
          if (t1_inout == 'i' && t2_inout == 'o')
            {
              conflict = 'a';
              continue;
            }
          if (t1_inout == 'i' && t2_inout == 'o')
            {
              conflict = 'a';
              continue;
            }
-         
+
          if (t1_inout != 'i' && t2_inout != 'i')
            return 'e';
        }
     }
 
          if (t1_inout != 'i' && t2_inout != 'i')
            return 'e';
        }
     }
 
-  if (t1_volatile && t2_volatile)
-    return 'f';
-  
   return conflict;
 }
 
   return conflict;
 }
 
@@ -6512,6 +6392,9 @@ xg_find_narrowest_format (vliw_insn *vinsn)
   vliw_insn v_copy = *vinsn;
   xtensa_opcode nop_opcode = xtensa_nop_opcode;
 
   vliw_insn v_copy = *vinsn;
   xtensa_opcode nop_opcode = xtensa_nop_opcode;
 
+  if (vinsn->num_slots == 1)
+    return xg_get_single_format (vinsn->slots[0].opcode);
+
   for (format = 0; format < xtensa_isa_num_formats (isa); format++)
     {
       v_copy = *vinsn;
   for (format = 0; format < xtensa_isa_num_formats (isa); format++)
     {
       v_copy = *vinsn;
@@ -6537,22 +6420,11 @@ xg_find_narrowest_format (vliw_insn *vinsn)
                  /* Try the widened version.  */
                  if (!v_copy.slots[slot].keep_wide
                      && !v_copy.slots[slot].is_specific_opcode
                  /* Try the widened version.  */
                  if (!v_copy.slots[slot].keep_wide
                      && !v_copy.slots[slot].is_specific_opcode
-                     && xg_is_narrow_insn (&v_copy.slots[slot])
-                     && !xg_expand_narrow (&widened, &v_copy.slots[slot])
+                     && xg_is_single_relaxable_insn (&v_copy.slots[slot],
+                                                     &widened, TRUE)
                      && opcode_fits_format_slot (widened.opcode,
                                                  format, slot))
                    {
                      && opcode_fits_format_slot (widened.opcode,
                                                  format, slot))
                    {
-                     /* The xg_is_narrow clause requires some explanation:
-
-                        addi can be "widened" to an addmi, which is then
-                        expanded to an addmi/addi pair if the immediate
-                        requires it, but here we must have a single widen
-                        only.
-
-                        xg_is_narrow tells us that addi isn't really
-                        narrow.  The widen_spec_list says that there are
-                        other cases.  */
-
                      v_copy.slots[slot] = widened;
                      fit++;
                    }
                      v_copy.slots[slot] = widened;
                      fit++;
                    }
@@ -6581,8 +6453,9 @@ xg_find_narrowest_format (vliw_insn *vinsn)
    each tinsn in the vinsn.  */
 
 static int
    each tinsn in the vinsn.  */
 
 static int
-relaxation_requirements (vliw_insn *vinsn)
+relaxation_requirements (vliw_insn *vinsn, bfd_boolean *pfinish_frag)
 {
 {
+  bfd_boolean finish_frag = FALSE;
   int extra_space = 0;
   int slot;
 
   int extra_space = 0;
   int slot;
 
@@ -6593,20 +6466,13 @@ relaxation_requirements (vliw_insn *vinsn)
        {
          /* A narrow instruction could be widened later to help
             alignment issues.  */
        {
          /* A narrow instruction could be widened later to help
             alignment issues.  */
-         if (xg_is_narrow_insn (tinsn)
+         if (xg_is_single_relaxable_insn (tinsn, 0, TRUE)
              && !tinsn->is_specific_opcode
              && vinsn->num_slots == 1)
            {
              /* Difference in bytes between narrow and wide insns...  */
              extra_space += 1;
              tinsn->subtype = RELAX_NARROW;
              && !tinsn->is_specific_opcode
              && vinsn->num_slots == 1)
            {
              /* Difference in bytes between narrow and wide insns...  */
              extra_space += 1;
              tinsn->subtype = RELAX_NARROW;
-             tinsn->record_fix = TRUE;
-             break;
-           }
-         else
-           {
-             tinsn->record_fix = FALSE;
-             /* No extra_space needed.  */
            }
        }
       else
            }
        }
       else
@@ -6619,7 +6485,7 @@ relaxation_requirements (vliw_insn *vinsn)
              extra_space += 3; /* for the nop size */
              tinsn->subtype = RELAX_ADD_NOP_IF_PRE_LOOP_END;
            }
              extra_space += 3; /* for the nop size */
              tinsn->subtype = RELAX_ADD_NOP_IF_PRE_LOOP_END;
            }
-         
+
          /* Need to assemble it with space for the relocation.  */
          if (xg_is_relaxable_insn (tinsn, 0)
              && !tinsn->is_specific_opcode)
          /* Need to assemble it with space for the relocation.  */
          if (xg_is_relaxable_insn (tinsn, 0)
              && !tinsn->is_specific_opcode)
@@ -6627,59 +6493,48 @@ relaxation_requirements (vliw_insn *vinsn)
              int max_size = xg_get_max_insn_widen_size (tinsn->opcode);
              int max_literal_size =
                xg_get_max_insn_widen_literal_size (tinsn->opcode);
              int max_size = xg_get_max_insn_widen_size (tinsn->opcode);
              int max_literal_size =
                xg_get_max_insn_widen_literal_size (tinsn->opcode);
-             
+
              tinsn->literal_space = max_literal_size;
              tinsn->literal_space = max_literal_size;
-             
+
              tinsn->subtype = RELAX_IMMED;
              tinsn->subtype = RELAX_IMMED;
-             tinsn->record_fix = FALSE;
              extra_space += max_size;
            }
          else
            {
              extra_space += max_size;
            }
          else
            {
-             tinsn->record_fix = TRUE;
-             /* No extra space needed.  */
+             /* A fix record will be added for this instruction prior
+                to relaxation, so make it end the frag.  */
+             finish_frag = TRUE;
            }
        }
     }
            }
        }
     }
+  *pfinish_frag = finish_frag;
   return extra_space;
 }
 
 
 static void
   return extra_space;
 }
 
 
 static void
-bundle_single_op (TInsn *orig_insn)
+bundle_tinsn (TInsn *tinsn, vliw_insn *vinsn)
 {
   xtensa_isa isa = xtensa_default_isa;
 {
   xtensa_isa isa = xtensa_default_isa;
-  vliw_insn v;
-  int slot;
-
-  xg_init_vinsn (&v);
-  v.format = op_placement_table[orig_insn->opcode].narrowest;
-  assert (v.format != XTENSA_UNDEFINED);
-  v.num_slots = xtensa_format_num_slots (isa, v.format);
+  int slot, chosen_slot;
 
 
-  for (slot = 0;
-       !opcode_fits_format_slot (orig_insn->opcode, v.format, slot);
-       slot++)
-    {
-      v.slots[slot].opcode =
-       xtensa_format_slot_nop_opcode (isa, v.format, slot);
-      v.slots[slot].ntok = 0;
-      v.slots[slot].insn_type = ITYPE_INSN;
-    }
-
-  v.slots[slot] = *orig_insn;
-  slot++;
+  vinsn->format = xg_get_single_format (tinsn->opcode);
+  assert (vinsn->format != XTENSA_UNDEFINED);
+  vinsn->num_slots = xtensa_format_num_slots (isa, vinsn->format);
 
 
-  for ( ; slot < v.num_slots; slot++)
+  chosen_slot = xg_get_single_slot (tinsn->opcode);
+  for (slot = 0; slot < vinsn->num_slots; slot++)
     {
     {
-      v.slots[slot].opcode =
-       xtensa_format_slot_nop_opcode (isa, v.format, slot);
-      v.slots[slot].ntok = 0;
-      v.slots[slot].insn_type = ITYPE_INSN;
+      if (slot == chosen_slot)
+       vinsn->slots[slot] = *tinsn;
+      else
+       {
+         vinsn->slots[slot].opcode =
+           xtensa_format_slot_nop_opcode (isa, vinsn->format, slot);
+         vinsn->slots[slot].ntok = 0;
+         vinsn->slots[slot].insn_type = ITYPE_INSN;
+       }
     }
     }
-
-  finish_vinsn (&v);
-  xg_free_vinsn (&v);
 }
 
 
 }
 
 
@@ -6694,10 +6549,10 @@ emit_single_op (TInsn *orig_insn)
   istack_init (&istack);
 
   /* Special-case for "movi aX, foo" which is guaranteed to need relaxing.
   istack_init (&istack);
 
   /* Special-case for "movi aX, foo" which is guaranteed to need relaxing.
-     Because the scheduling and bundling characteristics of movi and 
-     l32r or const16 are so different, we can do much better if we relax 
+     Because the scheduling and bundling characteristics of movi and
+     l32r or const16 are so different, we can do much better if we relax
      it prior to scheduling and bundling, rather than after.  */
      it prior to scheduling and bundling, rather than after.  */
-  if ((orig_insn->opcode == xtensa_movi_opcode 
+  if ((orig_insn->opcode == xtensa_movi_opcode
        || orig_insn->opcode == xtensa_movi_n_opcode)
       && !cur_vinsn.inside_bundle
       && (orig_insn->tok[1].X_op == O_symbol
        || orig_insn->opcode == xtensa_movi_n_opcode)
       && !cur_vinsn.inside_bundle
       && (orig_insn->tok[1].X_op == O_symbol
@@ -6710,7 +6565,7 @@ emit_single_op (TInsn *orig_insn)
   for (i = 0; i < istack.ninsn; i++)
     {
       TInsn *insn = &istack.insn[i];
   for (i = 0; i < istack.ninsn; i++)
     {
       TInsn *insn = &istack.insn[i];
-      switch (insn->insn_type) 
+      switch (insn->insn_type)
        {
        case ITYPE_LITERAL:
          assert (lit_sym == NULL);
        {
        case ITYPE_LITERAL:
          assert (lit_sym == NULL);
@@ -6729,11 +6584,17 @@ emit_single_op (TInsn *orig_insn)
          }
          break;
        case ITYPE_INSN:
          }
          break;
        case ITYPE_INSN:
-         if (lit_sym)
-           xg_resolve_literals (insn, lit_sym);
-         if (label_sym)
-           xg_resolve_labels (insn, label_sym);
-         bundle_single_op (insn);
+         {
+           vliw_insn v;
+           if (lit_sym)
+             xg_resolve_literals (insn, lit_sym);
+           if (label_sym)
+             xg_resolve_labels (insn, label_sym);
+           xg_init_vinsn (&v);
+           bundle_tinsn (insn, &v);
+           finish_vinsn (&v);
+           xg_free_vinsn (&v);
+         }
          break;
        default:
          assert (0);
          break;
        default:
          assert (0);
@@ -6762,7 +6623,7 @@ total_frag_text_expansion (fragS *fragP)
 static void
 xg_assemble_vliw_tokens (vliw_insn *vinsn)
 {
 static void
 xg_assemble_vliw_tokens (vliw_insn *vinsn)
 {
-  bfd_boolean finish_frag = FALSE;
+  bfd_boolean finish_frag;
   bfd_boolean is_jump = FALSE;
   bfd_boolean is_branch = FALSE;
   xtensa_isa isa = xtensa_default_isa;
   bfd_boolean is_jump = FALSE;
   bfd_boolean is_branch = FALSE;
   xtensa_isa isa = xtensa_default_isa;
@@ -6771,9 +6632,10 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
   int extra_space;
   char *f = NULL;
   int slot;
   int extra_space;
   char *f = NULL;
   int slot;
-  struct dwarf2_line_info best_loc;
+  unsigned current_line, best_linenum;
+  char *current_file;
 
 
-  best_loc.line = INT_MAX;
+  best_linenum = UINT_MAX;
 
   if (generating_literals)
     {
 
   if (generating_literals)
     {
@@ -6791,6 +6653,8 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
       && (! frag_now->tc_frag_data.is_insn
          || (vinsn_has_specific_opcodes (vinsn) && use_transform ())
          || !use_transform () != frag_now->tc_frag_data.is_no_transform
       && (! frag_now->tc_frag_data.is_insn
          || (vinsn_has_specific_opcodes (vinsn) && use_transform ())
          || !use_transform () != frag_now->tc_frag_data.is_no_transform
+         || (directive_state[directive_longcalls]
+             != frag_now->tc_frag_data.use_longcalls)
          || (directive_state[directive_absolute_literals]
              != frag_now->tc_frag_data.use_absolute_literals)))
     {
          || (directive_state[directive_absolute_literals]
              != frag_now->tc_frag_data.use_absolute_literals)))
     {
@@ -6831,21 +6695,21 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
       /* See if the instruction implies an aligned section.  */
       if (xtensa_opcode_is_loop (isa, vinsn->slots[i].opcode) == 1)
        record_alignment (now_seg, 2);
       /* See if the instruction implies an aligned section.  */
       if (xtensa_opcode_is_loop (isa, vinsn->slots[i].opcode) == 1)
        record_alignment (now_seg, 2);
-      
+
       /* Also determine the best line number for debug info.  */
       /* Also determine the best line number for debug info.  */
-      best_loc = vinsn->slots[i].loc.line < best_loc.line 
-       ? vinsn->slots[i].loc : best_loc;
+      best_linenum = vinsn->slots[i].linenum < best_linenum
+       ? vinsn->slots[i].linenum : best_linenum;
     }
 
   /* Special cases for instructions that force an alignment... */
   /* None of these opcodes are bundle-able.  */
   if (xtensa_opcode_is_loop (isa, vinsn->slots[0].opcode) == 1)
     {
     }
 
   /* Special cases for instructions that force an alignment... */
   /* None of these opcodes are bundle-able.  */
   if (xtensa_opcode_is_loop (isa, vinsn->slots[0].opcode) == 1)
     {
-      size_t max_fill;
-      
+      int max_fill;
+
       xtensa_set_frag_assembly_state (frag_now);
       frag_now->tc_frag_data.is_insn = TRUE;
       xtensa_set_frag_assembly_state (frag_now);
       frag_now->tc_frag_data.is_insn = TRUE;
-      
+
       max_fill = get_text_align_max_fill_size
        (get_text_align_power (xtensa_fetch_width),
         TRUE, frag_now->tc_frag_data.is_no_density);
       max_fill = get_text_align_max_fill_size
        (get_text_align_power (xtensa_fetch_width),
         TRUE, frag_now->tc_frag_data.is_no_density);
@@ -6857,10 +6721,10 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
                  frag_now->fr_offset,
                  NULL);
       else
                  frag_now->fr_offset,
                  NULL);
       else
-       frag_var (rs_machine_dependent, 0, 0, 
+       frag_var (rs_machine_dependent, 0, 0,
                  RELAX_CHECK_ALIGN_NEXT_OPCODE, 0, 0, NULL);
       xtensa_set_frag_assembly_state (frag_now);
                  RELAX_CHECK_ALIGN_NEXT_OPCODE, 0, 0, NULL);
       xtensa_set_frag_assembly_state (frag_now);
-      
+
       xtensa_move_labels (frag_now, 0, FALSE);
     }
 
       xtensa_move_labels (frag_now, 0, FALSE);
     }
 
@@ -6886,31 +6750,35 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
 
   insn_size = xtensa_format_length (isa, vinsn->format);
 
 
   insn_size = xtensa_format_length (isa, vinsn->format);
 
-  extra_space = relaxation_requirements (vinsn);
+  extra_space = relaxation_requirements (vinsn, &finish_frag);
 
   /* vinsn_to_insnbuf will produce the error.  */
   if (vinsn->format != XTENSA_UNDEFINED)
     {
 
   /* vinsn_to_insnbuf will produce the error.  */
   if (vinsn->format != XTENSA_UNDEFINED)
     {
-      f = (char *) frag_more (insn_size + extra_space);
+      f = frag_more (insn_size + extra_space);
       xtensa_set_frag_assembly_state (frag_now);
       frag_now->tc_frag_data.is_insn = TRUE;
     }
 
       xtensa_set_frag_assembly_state (frag_now);
       frag_now->tc_frag_data.is_insn = TRUE;
     }
 
-  vinsn_to_insnbuf (vinsn, f, frag_now, TRUE);
+  vinsn_to_insnbuf (vinsn, f, frag_now, FALSE);
   if (vinsn->format == XTENSA_UNDEFINED)
     return;
 
   if (vinsn->format == XTENSA_UNDEFINED)
     return;
 
-  xtensa_insnbuf_to_chars (isa, vinsn->insnbuf, f, 0);
-  
-  xtensa_dwarf2_emit_insn (insn_size - extra_space, &best_loc);
+  xtensa_insnbuf_to_chars (isa, vinsn->insnbuf, (unsigned char *) f, 0);
+
+  /* Temporarily set the logical line number to the one we want to appear
+     in the debug information.  */
+  as_where (&current_file, &current_line);
+  new_logical_line (current_file, best_linenum);
+  dwarf2_emit_insn (insn_size + extra_space);
+  new_logical_line (current_file, current_line);
 
   for (slot = 0; slot < vinsn->num_slots; slot++)
     {
       TInsn *tinsn = &vinsn->slots[slot];
       frag_now->tc_frag_data.slot_subtypes[slot] = tinsn->subtype;
 
   for (slot = 0; slot < vinsn->num_slots; slot++)
     {
       TInsn *tinsn = &vinsn->slots[slot];
       frag_now->tc_frag_data.slot_subtypes[slot] = tinsn->subtype;
-      frag_now->tc_frag_data.slot_symbols[slot] =  tinsn->symbol;
-      frag_now->tc_frag_data.slot_sub_symbols[slot] =  tinsn->sub_symbol;
-      frag_now->tc_frag_data.slot_offsets[slot] =  tinsn->offset;
+      frag_now->tc_frag_data.slot_symbols[slot] = tinsn->symbol;
+      frag_now->tc_frag_data.slot_offsets[slot] = tinsn->offset;
       frag_now->tc_frag_data.literal_frags[slot] = tinsn->literal_frag;
       if (tinsn->literal_space != 0)
        xg_assemble_literal_space (tinsn->literal_space, slot);
       frag_now->tc_frag_data.literal_frags[slot] = tinsn->literal_frag;
       if (tinsn->literal_space != 0)
        xg_assemble_literal_space (tinsn->literal_space, slot);
@@ -6922,8 +6790,8 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
       if (xtensa_opcode_is_branch (isa, tinsn->opcode) == 1)
        is_branch = TRUE;
 
       if (xtensa_opcode_is_branch (isa, tinsn->opcode) == 1)
        is_branch = TRUE;
 
-      if (tinsn->subtype || tinsn->symbol || tinsn->record_fix 
-         || tinsn->offset || tinsn->literal_frag || is_jump || is_branch)
+      if (tinsn->subtype || tinsn->symbol || tinsn->offset
+         || tinsn->literal_frag || is_jump || is_branch)
        finish_frag = TRUE;
     }
 
        finish_frag = TRUE;
     }
 
@@ -6983,7 +6851,7 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
                    frag_now->fr_symbol, frag_now->fr_offset, NULL);
          xtensa_set_frag_assembly_state (frag_now);
        }
                    frag_now->fr_symbol, frag_now->fr_offset, NULL);
          xtensa_set_frag_assembly_state (frag_now);
        }
-      else if (is_branch && align_targets)
+      else if (is_branch && do_align_targets ())
        {
          assert (finish_frag);
          frag_var (rs_machine_dependent,
        {
          assert (finish_frag);
          frag_var (rs_machine_dependent,
@@ -7099,7 +6967,7 @@ xtensa_cleanup_align_frags (void)
              && fragP->fr_subtype == RELAX_SLOTS
              && fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
            frag_wane (fragP);
              && fragP->fr_subtype == RELAX_SLOTS
              && fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
            frag_wane (fragP);
-         if (fragP->fr_type == rs_machine_dependent 
+         if (fragP->fr_type == rs_machine_dependent
              && fragP->fr_subtype == RELAX_UNREACHABLE)
            fragP->tc_frag_data.is_unreachable = TRUE;
        }
              && fragP->fr_subtype == RELAX_UNREACHABLE)
            fragP->tc_frag_data.is_unreachable = TRUE;
        }
@@ -7110,11 +6978,7 @@ xtensa_cleanup_align_frags (void)
 /* Re-process all of the fragments looking to convert all of the
    RELAX_DESIRE_ALIGN_IF_TARGET fragments.  If there is a branch
    target in the next fragment, convert this to RELAX_DESIRE_ALIGN.
 /* Re-process all of the fragments looking to convert all of the
    RELAX_DESIRE_ALIGN_IF_TARGET fragments.  If there is a branch
    target in the next fragment, convert this to RELAX_DESIRE_ALIGN.
-   If the next fragment starts with a loop target, AND the previous
-   fragment can be expanded to negate the branch, convert this to a
-   RELAX_LOOP_END.  Otherwise, convert to a .fill 0.  */
-
-static bfd_boolean frag_can_negate_branch (fragS *);
+   Otherwise, convert to a .fill 0.  */
 
 static void
 xtensa_fix_target_frags (void)
 
 static void
 xtensa_fix_target_frags (void)
@@ -7125,7 +6989,6 @@ xtensa_fix_target_frags (void)
      so we walk over subsections instead of sections.  */
   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
     {
      so we walk over subsections instead of sections.  */
   for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
     {
-      bfd_boolean prev_frag_can_negate_branch = FALSE;
       fragS *fragP;
 
       /* Walk over all of the fragments in a subsection.  */
       fragS *fragP;
 
       /* Walk over all of the fragments in a subsection.  */
@@ -7134,61 +6997,16 @@ xtensa_fix_target_frags (void)
          if (fragP->fr_type == rs_machine_dependent
              && fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
            {
          if (fragP->fr_type == rs_machine_dependent
              && fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
            {
-             if (next_frag_is_loop_target (fragP))
-               {
-                 if (prev_frag_can_negate_branch)
-                   {
-                     fragP->fr_subtype = RELAX_LOOP_END;
-                     /* See the comment near the frag_var with a
-                        RELAX_DESIRE_ALIGN to see why we do this.  */
-                     fragP->fr_var = RELAX_LOOP_END_BYTES;
-                   }
-                 else
-                   {
-                     if (next_frag_is_branch_target (fragP))
-                       fragP->fr_subtype = RELAX_DESIRE_ALIGN;
-                     else
-                       frag_wane (fragP);
-                   }
-               }
-             else if (next_frag_is_branch_target (fragP))
+             if (next_frag_is_branch_target (fragP))
                fragP->fr_subtype = RELAX_DESIRE_ALIGN;
              else
                frag_wane (fragP);
            }
                fragP->fr_subtype = RELAX_DESIRE_ALIGN;
              else
                frag_wane (fragP);
            }
-         if (fragP->fr_fix != 0)
-           prev_frag_can_negate_branch = FALSE;
-         if (frag_can_negate_branch (fragP))
-           prev_frag_can_negate_branch = TRUE;
        }
     }
 }
 
 
        }
     }
 }
 
 
-static bfd_boolean
-frag_can_negate_branch (fragS *fragP)
-{
-  xtensa_isa isa = xtensa_default_isa;
-  vliw_insn vinsn;
-  int slot;
-
-  if (fragP->fr_type != rs_machine_dependent
-      || fragP->fr_subtype != RELAX_SLOTS)
-    return FALSE;
-
-  vinsn_from_chars (&vinsn, fragP->fr_opcode);
-
-  for (slot = 0; slot < xtensa_format_num_slots (isa, vinsn.format); slot++)
-    {
-      if ((fragP->tc_frag_data.slot_subtypes[slot] == RELAX_IMMED)
-         && xtensa_opcode_is_branch (isa, vinsn.slots[slot].opcode) == 1)
-       return TRUE;
-    }
-
-  return FALSE;
-}
-
-
 static bfd_boolean is_narrow_branch_guaranteed_in_range (fragS *, TInsn *);
 
 static void
 static bfd_boolean is_narrow_branch_guaranteed_in_range (fragS *, TInsn *);
 
 static void
@@ -7207,15 +7025,10 @@ xtensa_mark_narrow_branches (void)
              && fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED)
            {
              vliw_insn vinsn;
              && fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED)
            {
              vliw_insn vinsn;
-             const expressionS *expr;
-             symbolS *symbolP;
 
              vinsn_from_chars (&vinsn, fragP->fr_opcode);
              tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0);
 
 
              vinsn_from_chars (&vinsn, fragP->fr_opcode);
              tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0);
 
-             expr = &vinsn.slots[0].tok[1];
-             symbolP = expr->X_add_symbol;
-
              if (vinsn.num_slots == 1
                  && xtensa_opcode_is_branch (xtensa_default_isa,
                                              vinsn.slots[0].opcode)
              if (vinsn.num_slots == 1
                  && xtensa_opcode_is_branch (xtensa_default_isa,
                                              vinsn.slots[0].opcode)
@@ -7225,6 +7038,7 @@ xtensa_mark_narrow_branches (void)
                {
                  fragP->fr_subtype = RELAX_SLOTS;
                  fragP->tc_frag_data.slot_subtypes[0] = RELAX_NARROW;
                {
                  fragP->fr_subtype = RELAX_SLOTS;
                  fragP->tc_frag_data.slot_subtypes[0] = RELAX_NARROW;
+                 fragP->tc_frag_data.is_aligning_branch = 1;
                }
            }
        }
                }
            }
        }
@@ -7242,18 +7056,27 @@ xtensa_mark_narrow_branches (void)
    use for alignment narrow branches that definitely will not expand to a
    jump and a branch.  These functions find and mark these cases.  */
 
    use for alignment narrow branches that definitely will not expand to a
    jump and a branch.  These functions find and mark these cases.  */
 
-/* the range in bytes of a bnez.n and beqz.n */
-#define MAX_IMMED6 68
+/* The range in bytes of BNEZ.N and BEQZ.N.  The target operand is encoded
+   as PC + 4 + imm6, where imm6 is a 6-bit immediate ranging from 0 to 63.
+   We start counting beginning with the frag after the 2-byte branch, so the
+   maximum offset is (4 - 2) + 63 = 65.  */
+#define MAX_IMMED6 65
 
 
-static size_t unrelaxed_frag_max_size (fragS *);
+static offsetT unrelaxed_frag_max_size (fragS *);
 
 static bfd_boolean
 is_narrow_branch_guaranteed_in_range (fragS *fragP, TInsn *tinsn)
 {
   const expressionS *expr = &tinsn->tok[1];
   symbolS *symbolP = expr->X_add_symbol;
 
 static bfd_boolean
 is_narrow_branch_guaranteed_in_range (fragS *fragP, TInsn *tinsn)
 {
   const expressionS *expr = &tinsn->tok[1];
   symbolS *symbolP = expr->X_add_symbol;
-  fragS *target_frag = symbol_get_frag (symbolP);
-  size_t max_distance = expr->X_add_number;
+  offsetT max_distance = expr->X_add_number;
+  fragS *target_frag;
+
+  if (expr->X_op != O_symbol)
+    return FALSE;
+
+  target_frag = symbol_get_frag (symbolP);
+
   max_distance += (S_GET_VALUE (symbolP) - target_frag->fr_address);
   if (is_branch_jmp_to_next (tinsn, fragP))
     return FALSE;
   max_distance += (S_GET_VALUE (symbolP) - target_frag->fr_address);
   if (is_branch_jmp_to_next (tinsn, fragP))
     return FALSE;
@@ -7294,12 +7117,10 @@ xtensa_mark_zcl_first_insns (void)
 
              /* Of course, sometimes (mostly for toy test cases) a
                 zero-cost loop instruction is the last in a section.  */
 
              /* Of course, sometimes (mostly for toy test cases) a
                 zero-cost loop instruction is the last in a section.  */
-             if (targ_frag) 
-               {
-                 targ_frag->tc_frag_data.is_first_loop_insn = TRUE;
-                 if (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)
-                   frag_wane (fragP);
-               }
+             if (targ_frag)
+               targ_frag->tc_frag_data.is_first_loop_insn = TRUE;
+             if (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)
+               frag_wane (fragP);
            }
        }
     }
            }
        }
     }
@@ -7367,7 +7188,8 @@ next_instrs_are_b_retw (fragS *fragP)
     return FALSE;
 
   /* Check for the conditional branch.  */
     return FALSE;
 
   /* Check for the conditional branch.  */
-  xtensa_insnbuf_from_chars (isa, insnbuf, &next_fragP->fr_literal[offset], 0);
+  xtensa_insnbuf_from_chars
+    (isa, insnbuf, (unsigned char *) &next_fragP->fr_literal[offset], 0);
   fmt = xtensa_format_decode (isa, insnbuf);
   if (fmt == XTENSA_UNDEFINED)
     return FALSE;
   fmt = xtensa_format_decode (isa, insnbuf);
   if (fmt == XTENSA_UNDEFINED)
     return FALSE;
@@ -7395,7 +7217,8 @@ next_instrs_are_b_retw (fragS *fragP)
     return FALSE;
 
   /* Check for the retw/retw.n.  */
     return FALSE;
 
   /* Check for the retw/retw.n.  */
-  xtensa_insnbuf_from_chars (isa, insnbuf, &next_fragP->fr_literal[offset], 0);
+  xtensa_insnbuf_from_chars
+    (isa, insnbuf, (unsigned char *) &next_fragP->fr_literal[offset], 0);
   fmt = xtensa_format_decode (isa, insnbuf);
 
   /* Because RETW[.N] is not bundleable, a VLIW bundle here means that we
   fmt = xtensa_format_decode (isa, insnbuf);
 
   /* Because RETW[.N] is not bundleable, a VLIW bundle here means that we
@@ -7482,7 +7305,8 @@ next_instr_is_loop_end (fragS *fragP)
    make it at least 12 bytes away.  In any case close it off with a
    .fill 0.  */
 
    make it at least 12 bytes away.  In any case close it off with a
    .fill 0.  */
 
-static size_t min_bytes_to_other_loop_end (fragS *, fragS *, offsetT, size_t);
+static offsetT min_bytes_to_other_loop_end
+  (fragS *, fragS *, offsetT, offsetT);
 
 static void
 xtensa_fix_close_loop_end_frags (void)
 
 static void
 xtensa_fix_close_loop_end_frags (void)
@@ -7527,8 +7351,8 @@ xtensa_fix_close_loop_end_frags (void)
              && fragP->fr_type == rs_machine_dependent
              && fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END)
            {
              && fragP->fr_type == rs_machine_dependent
              && fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END)
            {
-             size_t min_bytes;
-             size_t bytes_added = 0;
+             offsetT min_bytes;
+             int bytes_added = 0;
 
 #define REQUIRED_LOOP_DIVIDING_BYTES 12
              /* Max out at 12.  */
 
 #define REQUIRED_LOOP_DIVIDING_BYTES 12
              /* Max out at 12.  */
@@ -7546,10 +7370,10 @@ xtensa_fix_close_loop_end_frags (void)
                             < REQUIRED_LOOP_DIVIDING_BYTES)
                        {
                          int length = 3;
                             < REQUIRED_LOOP_DIVIDING_BYTES)
                        {
                          int length = 3;
-                         
+
                          if (fragP->fr_var < length)
                            as_fatal (_("fr_var %lu < length %d"),
                          if (fragP->fr_var < length)
                            as_fatal (_("fr_var %lu < length %d"),
-                                     fragP->fr_var, length);
+                                     (long) fragP->fr_var, length);
                          else
                            {
                              assemble_nop (length,
                          else
                            {
                              assemble_nop (length,
@@ -7570,15 +7394,15 @@ xtensa_fix_close_loop_end_frags (void)
 }
 
 
 }
 
 
-static size_t unrelaxed_frag_min_size (fragS *);
+static offsetT unrelaxed_frag_min_size (fragS *);
 
 
-static size_t
+static offsetT
 min_bytes_to_other_loop_end (fragS *fragP,
                             fragS *current_target,
                             offsetT current_offset,
 min_bytes_to_other_loop_end (fragS *fragP,
                             fragS *current_target,
                             offsetT current_offset,
-                            size_t max_size)
+                            offsetT max_size)
 {
 {
-  size_t offset = 0;
+  offsetT offset = 0;
   fragS *current_fragP;
 
   for (current_fragP = fragP;
   fragS *current_fragP;
 
   for (current_fragP = fragP;
@@ -7598,12 +7422,12 @@ min_bytes_to_other_loop_end (fragS *fragP,
 }
 
 
 }
 
 
-static size_t
+static offsetT
 unrelaxed_frag_min_size (fragS *fragP)
 {
 unrelaxed_frag_min_size (fragS *fragP)
 {
-  size_t size = fragP->fr_fix;
+  offsetT size = fragP->fr_fix;
 
 
-  /* add fill size */
+  /* Add fill size.  */
   if (fragP->fr_type == rs_fill)
     size += fragP->fr_offset;
 
   if (fragP->fr_type == rs_fill)
     size += fragP->fr_offset;
 
@@ -7611,14 +7435,14 @@ unrelaxed_frag_min_size (fragS *fragP)
 }
 
 
 }
 
 
-static size_t
+static offsetT
 unrelaxed_frag_max_size (fragS *fragP)
 {
 unrelaxed_frag_max_size (fragS *fragP)
 {
-  size_t size = fragP->fr_fix;
+  offsetT size = fragP->fr_fix;
   switch (fragP->fr_type)
     {
     case 0:
   switch (fragP->fr_type)
     {
     case 0:
-      /* Empty frags created by the obstack allocation scheme 
+      /* Empty frags created by the obstack allocation scheme
         end up with type 0.  */
       break;
     case rs_fill:
         end up with type 0.  */
       break;
     case rs_fill:
@@ -7664,7 +7488,7 @@ unrelaxed_frag_max_size (fragS *fragP)
    then convert this frag (and maybe the next one) to generate a NOP.
    In any case close it off with a .fill 0.  */
 
    then convert this frag (and maybe the next one) to generate a NOP.
    In any case close it off with a .fill 0.  */
 
-static size_t count_insns_to_loop_end (fragS *, bfd_boolean, size_t);
+static int count_insns_to_loop_end (fragS *, bfd_boolean, int);
 static bfd_boolean branch_before_loop_end (fragS *);
 
 static void
 static bfd_boolean branch_before_loop_end (fragS *);
 
 static void
@@ -7712,9 +7536,7 @@ xtensa_fix_short_loop_frags (void)
          if (fragP->fr_type == rs_machine_dependent
              && fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP)
            {
          if (fragP->fr_type == rs_machine_dependent
              && fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP)
            {
-             size_t insn_count =
-               count_insns_to_loop_end (fragP->fr_next, TRUE, 3);
-             if (insn_count < 3
+             if (count_insns_to_loop_end (fragP->fr_next, TRUE, 3) < 3
                  && (branch_before_loop_end (fragP->fr_next)
                      || (workaround_all_short_loops
                          && current_opcode != XTENSA_UNDEFINED
                  && (branch_before_loop_end (fragP->fr_next)
                      || (workaround_all_short_loops
                          && current_opcode != XTENSA_UNDEFINED
@@ -7732,15 +7554,15 @@ xtensa_fix_short_loop_frags (void)
 }
 
 
 }
 
 
-static size_t unrelaxed_frag_min_insn_count (fragS *);
+static int unrelaxed_frag_min_insn_count (fragS *);
 
 
-static size_t
+static int
 count_insns_to_loop_end (fragS *base_fragP,
                         bfd_boolean count_relax_add,
 count_insns_to_loop_end (fragS *base_fragP,
                         bfd_boolean count_relax_add,
-                        size_t max_count)
+                        int max_count)
 {
   fragS *fragP = NULL;
 {
   fragS *fragP = NULL;
-  size_t insn_count = 0;
+  int insn_count = 0;
 
   fragP = base_fragP;
 
 
   fragP = base_fragP;
 
@@ -7768,12 +7590,12 @@ count_insns_to_loop_end (fragS *base_fragP,
 }
 
 
 }
 
 
-static size_t
+static int
 unrelaxed_frag_min_insn_count (fragS *fragP)
 {
   xtensa_isa isa = xtensa_default_isa;
   static xtensa_insnbuf insnbuf = NULL;
 unrelaxed_frag_min_insn_count (fragS *fragP)
 {
   xtensa_isa isa = xtensa_default_isa;
   static xtensa_insnbuf insnbuf = NULL;
-  size_t insn_count = 0;
+  int insn_count = 0;
   int offset = 0;
 
   if (!fragP->tc_frag_data.is_insn)
   int offset = 0;
 
   if (!fragP->tc_frag_data.is_insn)
@@ -7787,7 +7609,8 @@ unrelaxed_frag_min_insn_count (fragS *fragP)
     {
       xtensa_format fmt;
 
     {
       xtensa_format fmt;
 
-      xtensa_insnbuf_from_chars (isa, insnbuf, fragP->fr_literal + offset, 0);
+      xtensa_insnbuf_from_chars
+       (isa, insnbuf, (unsigned char *) fragP->fr_literal + offset, 0);
       fmt = xtensa_format_decode (isa, insnbuf);
 
       if (fmt == XTENSA_UNDEFINED)
       fmt = xtensa_format_decode (isa, insnbuf);
 
       if (fmt == XTENSA_UNDEFINED)
@@ -7840,7 +7663,8 @@ unrelaxed_frag_has_b_j (fragS *fragP)
       xtensa_format fmt;
       int slot;
 
       xtensa_format fmt;
       int slot;
 
-      xtensa_insnbuf_from_chars (isa, insnbuf, fragP->fr_literal + offset, 0);
+      xtensa_insnbuf_from_chars
+       (isa, insnbuf, (unsigned char *) fragP->fr_literal + offset, 0);
       fmt = xtensa_format_decode (isa, insnbuf);
       if (fmt == XTENSA_UNDEFINED)
        return FALSE;
       fmt = xtensa_format_decode (isa, insnbuf);
       if (fmt == XTENSA_UNDEFINED)
        return FALSE;
@@ -7868,7 +7692,7 @@ static void
 xtensa_sanity_check (void)
 {
   char *file_name;
 xtensa_sanity_check (void)
 {
   char *file_name;
-  int line;
+  unsigned line;
 
   frchainS *frchP;
 
 
   frchainS *frchP;
 
@@ -8013,21 +7837,23 @@ is_local_forward_loop (const TInsn *insn, fragS *fragP)
 \f
 /* Alignment Functions.  */
 
 \f
 /* Alignment Functions.  */
 
-static size_t
-get_text_align_power (int target_size)
+static int
+get_text_align_power (unsigned target_size)
 {
 {
-  size_t i = 0;
-  for (i = 0; i < sizeof (size_t); i++)
+  int i = 0;
+  unsigned power = 1;
+
+  assert (target_size <= INT_MAX);
+  while (target_size > power)
     {
     {
-      if (target_size <= (1 << i))
-       return i;
+      power <<= 1;
+      i += 1;
     }
     }
-  assert (0);
-  return 0;
+  return i;
 }
 
 
 }
 
 
-static addressT
+static int
 get_text_align_max_fill_size (int align_pow,
                              bfd_boolean use_nops,
                              bfd_boolean use_no_density)
 get_text_align_max_fill_size (int align_pow,
                              bfd_boolean use_nops,
                              bfd_boolean use_no_density)
@@ -8041,118 +7867,86 @@ get_text_align_max_fill_size (int align_pow,
 }
 
 
 }
 
 
-/* get_text_align_fill_size ()
-
-   Desired alignments:
-      give the address
-      target_size = size of next instruction
-      align_pow = get_text_align_power (target_size).
-      use_nops = 0
-      use_no_density = 0;
-   Loop alignments:
-      address = current address + loop instruction size;
-      target_size = 3 (for 2 or 3 byte target)
-                  = 4 (for 4 byte target)
-                  = 8 (for 8 byte target)
-      align_pow = get_text_align_power (target_size);
-      use_nops = 1
-      use_no_density = set appropriately
-   Text alignments:
-      address = current address + loop instruction size;
-      target_size = 0
-      align_pow = get_text_align_power (target_size);
-      use_nops = 0
-      use_no_density = 0.  */
+/* Calculate the minimum bytes of fill needed at "address" to align a
+   target instruction of size "target_size" so that it does not cross a
+   power-of-two boundary specified by "align_pow".  If "use_nops" is FALSE,
+   the fill can be an arbitrary number of bytes.  Otherwise, the space must
+   be filled by NOP instructions.  */
 
 
-static addressT
+static int
 get_text_align_fill_size (addressT address,
                          int align_pow,
                          int target_size,
                          bfd_boolean use_nops,
                          bfd_boolean use_no_density)
 {
 get_text_align_fill_size (addressT address,
                          int align_pow,
                          int target_size,
                          bfd_boolean use_nops,
                          bfd_boolean use_no_density)
 {
-  /* Input arguments:
-
-     align_pow: log2 (required alignment).
+  addressT alignment, fill, fill_limit, fill_step;
+  bfd_boolean skip_one = FALSE;
 
 
-     target_size: alignment must allow the new_address and
-     new_address+target_size-1.
+  alignment = (1 << align_pow);
+  assert (target_size > 0 && alignment >= (addressT) target_size);
 
 
-     use_nops: if TRUE, then we can only use 2- or 3-byte nops.
-
-     use_no_density: if use_nops and use_no_density, we can only use
-     3-byte nops.
-
-     Usually the align_pow is the power of 2 that is greater than 
-     or equal to the target_size.  This handles the 2-byte, 3-byte 
-     and 8-byte instructions.
-
-     Two cases:
-
-     (1) aligning an instruction properly, but without using NOPs.
-       E.G.: a 3-byte instruction can go on any address where address mod 4
-       is zero or one.  The aligner uses this case to find the optimal
-       number of fill bytes for relax_frag_for_align.
-
-     (2) aligning an instruction properly, but where we might need to use
-       extra NOPs.  E.G.: when the aligner couldn't find enough widenings
-       or similar to get the optimal location.  */
-
-  size_t alignment = (1 << align_pow);
-
-  assert (target_size != 0);
-  
   if (!use_nops)
     {
   if (!use_nops)
     {
-      unsigned fill_bytes;
-      for (fill_bytes = 0; fill_bytes < alignment; fill_bytes++)
-       {
-         addressT end_address = address + target_size - 1 + fill_bytes;
-         addressT start_address = address + fill_bytes;
-         if ((end_address >> align_pow) == (start_address >> align_pow))
-           return fill_bytes;
-       }
-      assert (0);
+      fill_limit = alignment;
+      fill_step = 1;
     }
     }
-
-  /* This is the slightly harder case.  */
-  assert ((int) alignment >= target_size);
-  assert (target_size > 0);
-  if (!use_no_density)
+  else if (!use_no_density)
     {
     {
-      size_t i;
-      for (i = 0; i < alignment * 2; i++)
-       {
-         if (i == 1)
-           continue;
-         if ((address + i) >> align_pow
-             == (address + i + target_size - 1) >> align_pow)
-           return i;
-       }
+      /* Combine 2- and 3-byte NOPs to fill anything larger than one.  */
+      fill_limit = alignment * 2;
+      fill_step = 1;
+      skip_one = TRUE;
     }
   else
     {
     }
   else
     {
-      size_t i;
+      /* Fill with 3-byte NOPs -- can only fill multiples of 3.  */
+      fill_limit = alignment * 3;
+      fill_step = 3;
+    }
 
 
-      /* Can only fill multiples of 3.  */
-      for (i = 0; i <= alignment * 3; i += 3)
-       {
-         if ((address + i) >> align_pow
-             == (address + i + target_size - 1) >> align_pow)
-           return i;
-       }
+  /* Try all fill sizes until finding one that works.  */
+  for (fill = 0; fill < fill_limit; fill += fill_step)
+    {
+      if (skip_one && fill == 1)
+       continue;
+      if ((address + fill) >> align_pow
+         == (address + fill + target_size - 1) >> align_pow)
+       return fill;
     }
   assert (0);
   return 0;
 }
 
 
     }
   assert (0);
   return 0;
 }
 
 
+static int
+branch_align_power (segT sec)
+{
+  /* If the Xtensa processor has a fetch width of 8 bytes, and the section
+     is aligned to at least an 8-byte boundary, then a branch target need
+     only fit within an 8-byte aligned block of memory to avoid a stall.
+     Otherwise, try to fit branch targets within 4-byte aligned blocks
+     (which may be insufficient, e.g., if the section has no alignment, but
+     it's good enough).  */
+  if (xtensa_fetch_width == 8)
+    {
+      if (get_recorded_alignment (sec) >= 3)
+       return 3;
+    }
+  else
+    assert (xtensa_fetch_width == 4);
+
+  return 2;
+}
+
+
 /* This will assert if it is not possible.  */
 
 /* This will assert if it is not possible.  */
 
-static size_t
-get_text_align_nop_count (size_t fill_size, bfd_boolean use_no_density)
+static int
+get_text_align_nop_count (offsetT fill_size, bfd_boolean use_no_density)
 {
 {
-  size_t count = 0;
+  int count = 0;
+
   if (use_no_density)
     {
       assert (fill_size % 3 == 0);
   if (use_no_density)
     {
       assert (fill_size % 3 == 0);
@@ -8163,7 +7957,7 @@ get_text_align_nop_count (size_t fill_size, bfd_boolean use_no_density)
 
   while (fill_size > 1)
     {
 
   while (fill_size > 1)
     {
-      size_t insn_size = 3;
+      int insn_size = 3;
       if (fill_size == 2 || fill_size == 4)
        insn_size = 2;
       fill_size -= insn_size;
       if (fill_size == 2 || fill_size == 4)
        insn_size = 2;
       fill_size -= insn_size;
@@ -8174,21 +7968,21 @@ get_text_align_nop_count (size_t fill_size, bfd_boolean use_no_density)
 }
 
 
 }
 
 
-static size_t
-get_text_align_nth_nop_size (size_t fill_size,
-                            size_t n,
+static int
+get_text_align_nth_nop_size (offsetT fill_size,
+                            int n,
                             bfd_boolean use_no_density)
 {
                             bfd_boolean use_no_density)
 {
-  size_t count = 0;
-
-  assert (get_text_align_nop_count (fill_size, use_no_density) > n);
+  int count = 0;
 
   if (use_no_density)
     return 3;
 
 
   if (use_no_density)
     return 3;
 
+  assert (fill_size != 1);     /* Bad argument.  */
+
   while (fill_size > 1)
     {
   while (fill_size > 1)
     {
-      size_t insn_size = 3;
+      int insn_size = 3;
       if (fill_size == 2 || fill_size == 4)
        insn_size = 2;
       fill_size -= insn_size;
       if (fill_size == 2 || fill_size == 4)
        insn_size = 2;
       fill_size -= insn_size;
@@ -8211,21 +8005,21 @@ get_noop_aligned_address (fragS *fragP, addressT address)
      the smallest number of bytes that need to be added to
      ensure that the next fragment's FIRST instruction will fit
      in a single word.
      the smallest number of bytes that need to be added to
      ensure that the next fragment's FIRST instruction will fit
      in a single word.
-     
+
      E.G.,   2 bytes : 0, 1, 2 mod 4
             3 bytes: 0, 1 mod 4
      E.G.,   2 bytes : 0, 1, 2 mod 4
             3 bytes: 0, 1 mod 4
-     
+
      If the FIRST instruction MIGHT be relaxed,
      assume that it will become a 3-byte instruction.
      If the FIRST instruction MIGHT be relaxed,
      assume that it will become a 3-byte instruction.
-     
+
      Note again here that LOOP instructions are not bundleable,
      and this relaxation only applies to LOOP opcodes.  */
      Note again here that LOOP instructions are not bundleable,
      and this relaxation only applies to LOOP opcodes.  */
-  
-  size_t fill_size = 0;
+
+  int fill_size = 0;
   int first_insn_size;
   int loop_insn_size;
   addressT pre_opcode_bytes;
   int first_insn_size;
   int loop_insn_size;
   addressT pre_opcode_bytes;
-  size_t alignment;
+  int align_power;
   fragS *first_insn;
   xtensa_opcode opcode;
   bfd_boolean is_loop;
   fragS *first_insn;
   xtensa_opcode opcode;
   bfd_boolean is_loop;
@@ -8259,15 +8053,12 @@ get_noop_aligned_address (fragS *fragP, addressT address)
     first_insn_size = 3;       /* ISA specifies this */
 
   /* If it was 8, then we'll need a larger alignment for the section.  */
     first_insn_size = 3;       /* ISA specifies this */
 
   /* If it was 8, then we'll need a larger alignment for the section.  */
-  alignment = get_text_align_power (first_insn_size);
+  align_power = get_text_align_power (first_insn_size);
+  record_alignment (now_seg, align_power);
 
 
-  /* Is now_seg valid?  */
-  record_alignment (now_seg, alignment);
-  
   fill_size = get_text_align_fill_size
   fill_size = get_text_align_fill_size
-    (address + pre_opcode_bytes,
-     get_text_align_power (first_insn_size),
-     first_insn_size, TRUE, fragP->tc_frag_data.is_no_density);
+    (address + pre_opcode_bytes, align_power, first_insn_size, TRUE,
+     fragP->tc_frag_data.is_no_density);
 
   return address + fill_size;
 }
 
   return address + fill_size;
 }
@@ -8290,15 +8081,16 @@ get_noop_aligned_address (fragS *fragP, addressT address)
               >=5 : 3-byte instruction + fn (n-3)
    widening - widen previous instructions.  */
 
               >=5 : 3-byte instruction + fn (n-3)
    widening - widen previous instructions.  */
 
-static addressT
-get_aligned_diff (fragS *fragP, addressT address, addressT *max_diff)
+static offsetT
+get_aligned_diff (fragS *fragP, addressT address, offsetT *max_diff)
 {
   addressT target_address, loop_insn_offset;
   int target_size;
   xtensa_opcode loop_opcode;
   bfd_boolean is_loop;
 {
   addressT target_address, loop_insn_offset;
   int target_size;
   xtensa_opcode loop_opcode;
   bfd_boolean is_loop;
-  int text_align_power;
-  addressT opt_diff;
+  int align_power;
+  offsetT opt_diff;
+  offsetT branch_align;
 
   assert (fragP->fr_type == rs_machine_dependent);
   switch (fragP->fr_subtype)
 
   assert (fragP->fr_type == rs_machine_dependent);
   switch (fragP->fr_subtype)
@@ -8307,12 +8099,16 @@ get_aligned_diff (fragS *fragP, addressT address, addressT *max_diff)
       target_size = next_frag_format_size (fragP);
       if (target_size == XTENSA_UNDEFINED)
        target_size = 3;
       target_size = next_frag_format_size (fragP);
       if (target_size == XTENSA_UNDEFINED)
        target_size = 3;
-      text_align_power = get_text_align_power (xtensa_fetch_width);
-      opt_diff = get_text_align_fill_size (address, text_align_power,
+      align_power = branch_align_power (now_seg);
+      branch_align = 1 << align_power;
+      /* Don't count on the section alignment being as large as the target.  */
+      if (target_size > branch_align)
+       target_size = branch_align;
+      opt_diff = get_text_align_fill_size (address, align_power,
                                           target_size, FALSE, FALSE);
 
                                           target_size, FALSE, FALSE);
 
-      *max_diff = opt_diff + xtensa_fetch_width
-       - (target_size + ((address + opt_diff) % xtensa_fetch_width));
+      *max_diff = (opt_diff + branch_align
+                  - (target_size + ((address + opt_diff) % branch_align)));
       assert (*max_diff >= opt_diff);
       return opt_diff;
 
       assert (*max_diff >= opt_diff);
       return opt_diff;
 
@@ -8337,8 +8133,8 @@ get_aligned_diff (fragS *fragP, addressT address, addressT *max_diff)
         will call get_noop_aligned_address.  */
       target_address =
        address + loop_insn_offset + xg_get_single_size (loop_opcode);
         will call get_noop_aligned_address.  */
       target_address =
        address + loop_insn_offset + xg_get_single_size (loop_opcode);
-      text_align_power = get_text_align_power (target_size),
-      opt_diff = get_text_align_fill_size (target_address, text_align_power,
+      align_power = get_text_align_power (target_size),
+      opt_diff = get_text_align_fill_size (target_address, align_power,
                                           target_size, FALSE, FALSE);
 
       *max_diff = xtensa_fetch_width
                                           target_size, FALSE, FALSE);
 
       *max_diff = xtensa_fetch_width
@@ -8373,7 +8169,8 @@ xtensa_relax_frag (fragS *fragP, long stretch, int *stretched_p)
   int unreported = fragP->tc_frag_data.unreported_expansion;
   long new_stretch = 0;
   char *file_name;
   int unreported = fragP->tc_frag_data.unreported_expansion;
   long new_stretch = 0;
   char *file_name;
-  int line, lit_size;
+  unsigned line;
+  int lit_size;
   static xtensa_insnbuf vbuf = NULL;
   int slot, num_slots;
   xtensa_format fmt;
   static xtensa_insnbuf vbuf = NULL;
   int slot, num_slots;
   xtensa_format fmt;
@@ -8424,7 +8221,8 @@ xtensa_relax_frag (fragS *fragP, long stretch, int *stretched_p)
       if (vbuf == NULL)
        vbuf = xtensa_insnbuf_alloc (isa);
 
       if (vbuf == NULL)
        vbuf = xtensa_insnbuf_alloc (isa);
 
-      xtensa_insnbuf_from_chars (isa, vbuf, fragP->fr_opcode, 0);
+      xtensa_insnbuf_from_chars
+       (isa, vbuf, (unsigned char *) fragP->fr_opcode, 0);
       fmt = xtensa_format_decode (isa, vbuf);
       num_slots = xtensa_format_num_slots (isa, fmt);
 
       fmt = xtensa_format_decode (isa, vbuf);
       num_slots = xtensa_format_num_slots (isa, fmt);
 
@@ -8472,7 +8270,7 @@ xtensa_relax_frag (fragS *fragP, long stretch, int *stretched_p)
     }
 
   /* Tell gas we need another relaxation pass.  */
     }
 
   /* Tell gas we need another relaxation pass.  */
-  if (! fragP->tc_frag_data.relax_seen) 
+  if (! fragP->tc_frag_data.relax_seen)
     {
       fragP->tc_frag_data.relax_seen = TRUE;
       *stretched_p = 1;
     {
       fragP->tc_frag_data.relax_seen = TRUE;
       *stretched_p = 1;
@@ -8526,7 +8324,7 @@ relax_frag_add_nop (fragS *fragP)
 
   if (fragP->fr_var < length)
     {
 
   if (fragP->fr_var < length)
     {
-      as_fatal (_("fr_var (%ld) < length (%d)"), fragP->fr_var, length);
+      as_fatal (_("fr_var (%ld) < length (%d)"), (long) fragP->fr_var, length);
       return 0;
     }
 
       return 0;
     }
 
@@ -8607,7 +8405,7 @@ find_address_of_next_align_frag (fragS **fragPP,
   while (fragP)
     {
       /* Limit this to a small search.  */
   while (fragP)
     {
       /* Limit this to a small search.  */
-      if (*widens > 8)
+      if (*widens >= (int) xtensa_fetch_width)
        {
          *fragPP = fragP;
          return 0;
        {
          *fragPP = fragP;
          return 0;
@@ -8659,7 +8457,7 @@ find_address_of_next_align_frag (fragS **fragPP,
              return 0;
            }
        }
              return 0;
            }
        }
-      else 
+      else
        {
          /* Just punt if we don't know the type.  */
          *fragPP = fragP;
        {
          /* Just punt if we don't know the type.  */
          *fragPP = fragP;
@@ -8675,11 +8473,6 @@ find_address_of_next_align_frag (fragS **fragPP,
 
 static long bytes_to_stretch (fragS *, int, int, int, int);
 
 
 static long bytes_to_stretch (fragS *, int, int, int, int);
 
-/* Undefine LOOKAHEAD_ALIGNER to get the older behavior.
-   I'll leave this in until I am more confident this works.  */
-
-#define LOOKAHEAD_ALIGNER 1
-
 static long
 future_alignment_required (fragS *fragP, long stretch ATTRIBUTE_UNUSED)
 {
 static long
 future_alignment_required (fragS *fragP, long stretch ATTRIBUTE_UNUSED)
 {
@@ -8699,34 +8492,41 @@ future_alignment_required (fragS *fragP, long stretch ATTRIBUTE_UNUSED)
   address = find_address_of_next_align_frag
     (&fragP, &wide_nops, &narrow_nops, &num_widens, &paddable);
 
   address = find_address_of_next_align_frag
     (&fragP, &wide_nops, &narrow_nops, &num_widens, &paddable);
 
-  if (address)
+  if (!address)
+    {
+      if (this_frag->tc_frag_data.is_aligning_branch)
+       this_frag->tc_frag_data.slot_subtypes[0] = RELAX_IMMED;
+      else
+       frag_wane (this_frag);
+    }
+  else
     {
       local_opt_diff = get_aligned_diff (fragP, address, &max_diff);
       opt_diff = local_opt_diff;
       assert (opt_diff >= 0);
       assert (max_diff >= opt_diff);
     {
       local_opt_diff = get_aligned_diff (fragP, address, &max_diff);
       opt_diff = local_opt_diff;
       assert (opt_diff >= 0);
       assert (max_diff >= opt_diff);
-      if (max_diff == 0) 
+      if (max_diff == 0)
        return 0;
        return 0;
-#ifdef LOOKAHEAD_ALIGNER
+
       if (fragP)
        fragP = fragP->fr_next;
 
       while (fragP && opt_diff < max_diff && address)
        {
          /* We only use these to determine if we can exit early
       if (fragP)
        fragP = fragP->fr_next;
 
       while (fragP && opt_diff < max_diff && address)
        {
          /* We only use these to determine if we can exit early
-            because there will be plenty of ways to align future 
+            because there will be plenty of ways to align future
             align frags.  */
             align frags.  */
-         unsigned int glob_widens = 0;
+         int glob_widens = 0;
          int dnn = 0;
          int dw = 0;
          bfd_boolean glob_pad = 0;
          address = find_address_of_next_align_frag
            (&fragP, &glob_widens, &dnn, &dw, &glob_pad);
          /* If there is a padable portion, then skip.  */
          int dnn = 0;
          int dw = 0;
          bfd_boolean glob_pad = 0;
          address = find_address_of_next_align_frag
            (&fragP, &glob_widens, &dnn, &dw, &glob_pad);
          /* If there is a padable portion, then skip.  */
-         if (glob_pad || (glob_widens >= xtensa_fetch_width))
-           break;
+         if (glob_pad || glob_widens >= (1 << branch_align_power (now_seg)))
+           address = 0;
 
 
-         if (address) 
+         if (address)
            {
              offsetT next_m_diff;
              offsetT next_o_diff;
            {
              offsetT next_m_diff;
              offsetT next_o_diff;
@@ -8756,7 +8556,7 @@ future_alignment_required (fragS *fragP, long stretch ATTRIBUTE_UNUSED)
              fragP = fragP->fr_next;
            }
        }
              fragP = fragP->fr_next;
            }
        }
-#endif /* LOOKAHEAD_ALIGNER */
+
       /* If there are enough wideners in between, do it.  */
       if (paddable)
        {
       /* If there are enough wideners in between, do it.  */
       if (paddable)
        {
@@ -8767,24 +8567,21 @@ future_alignment_required (fragS *fragP, long stretch ATTRIBUTE_UNUSED)
            }
          return 0;
        }
            }
          return 0;
        }
-      local_stretch_amount 
+      local_stretch_amount
        = bytes_to_stretch (this_frag, wide_nops, narrow_nops,
                            num_widens, local_opt_diff);
        = bytes_to_stretch (this_frag, wide_nops, narrow_nops,
                            num_widens, local_opt_diff);
-#ifdef LOOKAHEAD_ALIGNER
-      global_stretch_amount 
-       = bytes_to_stretch (this_frag, wide_nops, narrow_nops, 
+      global_stretch_amount
+       = bytes_to_stretch (this_frag, wide_nops, narrow_nops,
                            num_widens, opt_diff);
                            num_widens, opt_diff);
-      /* If the condition below is true, then the frag couldn't 
-        stretch the correct amount for the global case, so we just 
-        optimize locally.  We'll rely on the subsequent frags to get 
+      /* If the condition below is true, then the frag couldn't
+        stretch the correct amount for the global case, so we just
+        optimize locally.  We'll rely on the subsequent frags to get
         the correct alignment in the global case.  */
       if (global_stretch_amount < local_stretch_amount)
        stretch_amount = local_stretch_amount;
       else
        stretch_amount = global_stretch_amount;
         the correct alignment in the global case.  */
       if (global_stretch_amount < local_stretch_amount)
        stretch_amount = local_stretch_amount;
       else
        stretch_amount = global_stretch_amount;
-#else /* ! LOOKAHEAD_ALIGNER */
-      stretch_amount = local_stretch_amount;
-#endif /* ! LOOKAHEAD_ALIGNER */
+
       if (this_frag->fr_subtype == RELAX_SLOTS
          && this_frag->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
        assert (stretch_amount <= 1);
       if (this_frag->fr_subtype == RELAX_SLOTS
          && this_frag->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
        assert (stretch_amount <= 1);
@@ -8850,7 +8647,7 @@ bytes_to_stretch (fragS *this_frag,
   assert (desired_diff >= 0 && desired_diff < 8);
   if (desired_diff == 0)
     return 0;
   assert (desired_diff >= 0 && desired_diff < 8);
   if (desired_diff == 0)
     return 0;
-  
+
   assert (wide_nops > 0 || num_widens > 0);
 
   /* Always prefer widening to NOP-filling.  */
   assert (wide_nops > 0 || num_widens > 0);
 
   /* Always prefer widening to NOP-filling.  */
@@ -8860,7 +8657,7 @@ bytes_to_stretch (fragS *this_frag,
         to align the target without widening this frag in any way.  */
       return 0;
     }
         to align the target without widening this frag in any way.  */
       return 0;
     }
-  
+
   if (bytes_short == 0)
     {
       /* Widen every narrow between here and the align target
   if (bytes_short == 0)
     {
       /* Widen every narrow between here and the align target
@@ -8870,7 +8667,7 @@ bytes_to_stretch (fragS *this_frag,
       else
        return 1;
     }
       else
        return 1;
     }
-  
+
   /* From here we will need at least one NOP to get an alignment.
      However, we may not be able to align at all, in which case,
      don't widen.  */
   /* From here we will need at least one NOP to get an alignment.
      However, we may not be able to align at all, in which case,
      don't widen.  */
@@ -8884,7 +8681,7 @@ bytes_to_stretch (fragS *this_frag,
          if (!this_frag->tc_frag_data.is_no_density && narrow_nops == 1)
            return 2; /* case 2 */
          return 0;
          if (!this_frag->tc_frag_data.is_no_density && narrow_nops == 1)
            return 2; /* case 2 */
          return 0;
-       case 3: 
+       case 3:
          if (wide_nops > 1)
            return 0;
          else
          if (wide_nops > 1)
            return 0;
          else
@@ -8898,7 +8695,7 @@ bytes_to_stretch (fragS *this_frag,
        case 5:
          if (num_widens >= 2 && wide_nops == 1)
            return 3; /* case 5a */
        case 5:
          if (num_widens >= 2 && wide_nops == 1)
            return 3; /* case 5a */
-         /* We will need two nops.  Are there enough nops 
+         /* We will need two nops.  Are there enough nops
             between here and the align target?  */
          if (wide_nops < 2 || narrow_nops == 0)
            return 0;
             between here and the align target?  */
          if (wide_nops < 2 || narrow_nops == 0)
            return 0;
@@ -8930,7 +8727,7 @@ bytes_to_stretch (fragS *this_frag,
     }
   else
     {
     }
   else
     {
-      /* We will need a NOP no matter what, but should we widen 
+      /* We will need a NOP no matter what, but should we widen
         this instruction to help?
 
         This is a RELAX_FRAG_NARROW frag.  */
         this instruction to help?
 
         This is a RELAX_FRAG_NARROW frag.  */
@@ -8983,7 +8780,6 @@ relax_frag_immed (segT segP,
                  bfd_boolean estimate_only)
 {
   TInsn tinsn;
                  bfd_boolean estimate_only)
 {
   TInsn tinsn;
-  vliw_insn orig_vinsn;
   int old_size;
   bfd_boolean negatable_branch = FALSE;
   bfd_boolean branch_jmp_to_next = FALSE;
   int old_size;
   bfd_boolean negatable_branch = FALSE;
   bfd_boolean branch_jmp_to_next = FALSE;
@@ -8998,12 +8794,12 @@ relax_frag_immed (segT segP,
 
   assert (fragP->fr_opcode != NULL);
 
 
   assert (fragP->fr_opcode != NULL);
 
-  xg_init_vinsn (&orig_vinsn);
-  vinsn_from_chars (&orig_vinsn, fragP->fr_opcode);
-  if (xtensa_format_num_slots (isa, fmt) > 1)
+  xg_clear_vinsn (&cur_vinsn);
+  vinsn_from_chars (&cur_vinsn, fragP->fr_opcode);
+  if (cur_vinsn.num_slots > 1)
     wide_insn = TRUE;
 
     wide_insn = TRUE;
 
-  tinsn = orig_vinsn.slots[slot];
+  tinsn = cur_vinsn.slots[slot];
   tinsn_immed_from_frag (&tinsn, fragP, slot);
 
   if (estimate_only && xtensa_opcode_is_loop (isa, tinsn.opcode))
   tinsn_immed_from_frag (&tinsn, fragP, slot);
 
   if (estimate_only && xtensa_opcode_is_loop (isa, tinsn.opcode))
@@ -9119,7 +8915,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragp)
   int num_slots;
   xtensa_format fmt;
   char *file_name;
   int num_slots;
   xtensa_format fmt;
   char *file_name;
-  int line;
+  unsigned line;
 
   as_where (&file_name, &line);
   new_logical_line (fragp->fr_file, fragp->fr_line);
 
   as_where (&file_name, &line);
   new_logical_line (fragp->fr_file, fragp->fr_line);
@@ -9143,7 +8939,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragp)
       if (vbuf == NULL)
        vbuf = xtensa_insnbuf_alloc (isa);
 
       if (vbuf == NULL)
        vbuf = xtensa_insnbuf_alloc (isa);
 
-      xtensa_insnbuf_from_chars (isa, vbuf, fragp->fr_opcode, 0);
+      xtensa_insnbuf_from_chars
+       (isa, vbuf, (unsigned char *) fragp->fr_opcode, 0);
       fmt = xtensa_format_decode (isa, vbuf);
       num_slots = xtensa_format_num_slots (isa, fmt);
 
       fmt = xtensa_format_decode (isa, vbuf);
       num_slots = xtensa_format_num_slots (isa, fmt);
 
@@ -9228,11 +9025,10 @@ static void
 convert_frag_align_next_opcode (fragS *fragp)
 {
   char *nop_buf;               /* Location for Writing.  */
 convert_frag_align_next_opcode (fragS *fragp)
 {
   char *nop_buf;               /* Location for Writing.  */
-  size_t i;
-
   bfd_boolean use_no_density = fragp->tc_frag_data.is_no_density;
   addressT aligned_address;
   bfd_boolean use_no_density = fragp->tc_frag_data.is_no_density;
   addressT aligned_address;
-  size_t fill_size, nop_count;
+  offsetT fill_size;
+  int nop, nop_count;
 
   aligned_address = get_noop_aligned_address (fragp, fragp->fr_address +
                                              fragp->fr_fix);
 
   aligned_address = get_noop_aligned_address (fragp, fragp->fr_address +
                                              fragp->fr_fix);
@@ -9240,10 +9036,10 @@ convert_frag_align_next_opcode (fragS *fragp)
   nop_count = get_text_align_nop_count (fill_size, use_no_density);
   nop_buf = fragp->fr_literal + fragp->fr_fix;
 
   nop_count = get_text_align_nop_count (fill_size, use_no_density);
   nop_buf = fragp->fr_literal + fragp->fr_fix;
 
-  for (i = 0; i < nop_count; i++)
+  for (nop = 0; nop < nop_count; nop++)
     {
     {
-      size_t nop_size;
-      nop_size = get_text_align_nth_nop_size (fill_size, i, use_no_density);
+      int nop_size;
+      nop_size = get_text_align_nth_nop_size (fill_size, nop, use_no_density);
 
       assemble_nop (nop_size, nop_buf);
       nop_buf += nop_size;
 
       assemble_nop (nop_size, nop_buf);
       nop_buf += nop_size;
@@ -9258,14 +9054,13 @@ static void
 convert_frag_narrow (segT segP, fragS *fragP, xtensa_format fmt, int slot)
 {
   TInsn tinsn, single_target;
 convert_frag_narrow (segT segP, fragS *fragP, xtensa_format fmt, int slot)
 {
   TInsn tinsn, single_target;
-  xtensa_format single_fmt;
-  int size, old_size, diff, error_val;
+  int size, old_size, diff;
   offsetT frag_offset;
 
   assert (slot == 0);
   tinsn_from_chars (&tinsn, fragP->fr_opcode, 0);
 
   offsetT frag_offset;
 
   assert (slot == 0);
   tinsn_from_chars (&tinsn, fragP->fr_opcode, 0);
 
-  if (xtensa_opcode_is_branch (xtensa_default_isa, tinsn.opcode) == 1)
+  if (fragP->tc_frag_data.is_aligning_branch == 1)
     {
       assert (fragP->tc_frag_data.text_expansion[0] == 1
              || fragP->tc_frag_data.text_expansion[0] == 0);
     {
       assert (fragP->tc_frag_data.text_expansion[0] == 1
              || fragP->tc_frag_data.text_expansion[0] == 0);
@@ -9294,18 +9089,15 @@ convert_frag_narrow (segT segP, fragS *fragP, xtensa_format fmt, int slot)
   tinsn_init (&single_target);
   frag_offset = fragP->fr_opcode - fragP->fr_literal;
 
   tinsn_init (&single_target);
   frag_offset = fragP->fr_opcode - fragP->fr_literal;
 
-  error_val = xg_expand_narrow (&single_target, &tinsn);
-  if (error_val)
+  if (! xg_is_single_relaxable_insn (&tinsn, &single_target, FALSE))
     {
       as_bad (_("unable to widen instruction"));
       return;
     }
 
   size = xg_get_single_size (single_target.opcode);
     {
       as_bad (_("unable to widen instruction"));
       return;
     }
 
   size = xg_get_single_size (single_target.opcode);
-  single_fmt = xg_get_single_format (single_target.opcode);
-
-  xg_emit_insn_to_buf (&single_target, single_fmt, fragP->fr_opcode,
-                      fragP, frag_offset, TRUE);
+  xg_emit_insn_to_buf (&single_target, fragP->fr_opcode, fragP,
+                      frag_offset, TRUE);
 
   diff = size - old_size;
   assert (diff >= 0);
 
   diff = size - old_size;
   assert (diff >= 0);
@@ -9356,7 +9148,6 @@ convert_frag_immed (segT segP,
   bfd_boolean expanded = FALSE;
   bfd_boolean branch_jmp_to_next = FALSE;
   char *fr_opcode = fragP->fr_opcode;
   bfd_boolean expanded = FALSE;
   bfd_boolean branch_jmp_to_next = FALSE;
   char *fr_opcode = fragP->fr_opcode;
-  vliw_insn orig_vinsn;
   xtensa_isa isa = xtensa_default_isa;
   bfd_boolean wide_insn = FALSE;
   int bytes;
   xtensa_isa isa = xtensa_default_isa;
   bfd_boolean wide_insn = FALSE;
   int bytes;
@@ -9364,13 +9155,13 @@ convert_frag_immed (segT segP,
 
   assert (fr_opcode != NULL);
 
 
   assert (fr_opcode != NULL);
 
-  xg_init_vinsn (&orig_vinsn);
+  xg_clear_vinsn (&cur_vinsn);
 
 
-  vinsn_from_chars (&orig_vinsn, fr_opcode);
-  if (xtensa_format_num_slots (isa, fmt) > 1)
+  vinsn_from_chars (&cur_vinsn, fr_opcode);
+  if (cur_vinsn.num_slots > 1)
     wide_insn = TRUE;
 
     wide_insn = TRUE;
 
-  orig_tinsn = orig_vinsn.slots[slot];
+  orig_tinsn = cur_vinsn.slots[slot];
   tinsn_immed_from_frag (&orig_tinsn, fragP, slot);
 
   is_loop = xtensa_opcode_is_loop (xtensa_default_isa, orig_tinsn.opcode) == 1;
   tinsn_immed_from_frag (&orig_tinsn, fragP, slot);
 
   is_loop = xtensa_opcode_is_loop (xtensa_default_isa, orig_tinsn.opcode) == 1;
@@ -9384,22 +9175,23 @@ convert_frag_immed (segT segP,
       bytes = xtensa_format_length (isa, fmt);
       if (bytes >= 4)
        {
       bytes = xtensa_format_length (isa, fmt);
       if (bytes >= 4)
        {
-         orig_vinsn.slots[slot].opcode =
-           xtensa_format_slot_nop_opcode (isa, orig_vinsn.format, slot);
-         orig_vinsn.slots[slot].ntok = 0;
+         cur_vinsn.slots[slot].opcode =
+           xtensa_format_slot_nop_opcode (isa, cur_vinsn.format, slot);
+         cur_vinsn.slots[slot].ntok = 0;
        }
       else
        {
          bytes += fragP->tc_frag_data.text_expansion[0];
          assert (bytes == 2 || bytes == 3);
        }
       else
        {
          bytes += fragP->tc_frag_data.text_expansion[0];
          assert (bytes == 2 || bytes == 3);
-         build_nop (&orig_vinsn.slots[0], bytes);
+         build_nop (&cur_vinsn.slots[0], bytes);
          fragP->fr_fix += fragP->tc_frag_data.text_expansion[0];
        }
          fragP->fr_fix += fragP->tc_frag_data.text_expansion[0];
        }
-      vinsn_to_insnbuf (&orig_vinsn, fr_opcode, frag_now, FALSE);
-      xtensa_insnbuf_to_chars (isa, orig_vinsn.insnbuf, fr_opcode, 0);
+      vinsn_to_insnbuf (&cur_vinsn, fr_opcode, frag_now, TRUE);
+      xtensa_insnbuf_to_chars
+       (isa, cur_vinsn.insnbuf, (unsigned char *) fr_opcode, 0);
       fragP->fr_var = 0;
     }
       fragP->fr_var = 0;
     }
-  else if (!orig_tinsn.is_specific_opcode)
+  else
     {
       /* Here is the fun stuff:  Get the immediate field from this
         instruction.  If it fits, we're done.  If not, find the next
     {
       /* Here is the fun stuff:  Get the immediate field from this
         instruction.  If it fits, we're done.  If not, find the next
@@ -9529,68 +9321,32 @@ convert_frag_immed (segT segP,
                  first = FALSE;
                  if (opcode_fits_format_slot (tinsn->opcode, fmt, slot))
                    {
                  first = FALSE;
                  if (opcode_fits_format_slot (tinsn->opcode, fmt, slot))
                    {
-                     tinsn->record_fix = TRUE;
-                     orig_vinsn.slots[slot] = *tinsn;
+                     cur_vinsn.slots[slot] = *tinsn;
                    }
                  else
                    {
                    }
                  else
                    {
-                     orig_vinsn.slots[slot].opcode =
+                     cur_vinsn.slots[slot].opcode =
                        xtensa_format_slot_nop_opcode (isa, fmt, slot);
                        xtensa_format_slot_nop_opcode (isa, fmt, slot);
-                     orig_vinsn.slots[slot].ntok = 0;
-                     orig_vinsn.slots[slot].record_fix = FALSE;
+                     cur_vinsn.slots[slot].ntok = 0;
                    }
                    }
-                 vinsn_to_insnbuf (&orig_vinsn, immed_instr, fragP, TRUE);
-                 xtensa_insnbuf_to_chars (isa, orig_vinsn.insnbuf,
-                                          immed_instr, 0);
+                 vinsn_to_insnbuf (&cur_vinsn, immed_instr, fragP, TRUE);
+                 xtensa_insnbuf_to_chars (isa, cur_vinsn.insnbuf,
+                                          (unsigned char *) immed_instr, 0);
                  fragP->tc_frag_data.is_insn = TRUE;
                  size = xtensa_format_length (isa, fmt);
                  if (!opcode_fits_format_slot (tinsn->opcode, fmt, slot))
                    {
                  fragP->tc_frag_data.is_insn = TRUE;
                  size = xtensa_format_length (isa, fmt);
                  if (!opcode_fits_format_slot (tinsn->opcode, fmt, slot))
                    {
-                     xtensa_format single_fmt =
-                       xg_get_single_format (tinsn->opcode);
-
                      xg_emit_insn_to_buf
                      xg_emit_insn_to_buf
-                       (tinsn, single_fmt, immed_instr + size, fragP,
+                       (tinsn, immed_instr + size, fragP,
                         immed_instr - fragP->fr_literal + size, TRUE);
                      size += xg_get_single_size (tinsn->opcode);
                    }
                }
              else
                {
                         immed_instr - fragP->fr_literal + size, TRUE);
                      size += xg_get_single_size (tinsn->opcode);
                    }
                }
              else
                {
-                 xtensa_format single_format;
                  size = xg_get_single_size (tinsn->opcode);
                  size = xg_get_single_size (tinsn->opcode);
-                 single_format = xg_get_single_format (tinsn->opcode);
-                 xg_emit_insn_to_buf (tinsn, single_format, immed_instr,
-                                      fragP,
+                 xg_emit_insn_to_buf (tinsn, immed_instr, fragP,
                                       immed_instr - fragP->fr_literal, TRUE);
                                       immed_instr - fragP->fr_literal, TRUE);
-#if 0
-                 /* Code to recognize branch-around expansion
-                    so the fragment is properly marked as ending in a
-                    jump. */
-                 if ((((i == istack.ninsn - 2)
-                       && (istack.insn[istack.ninsn-1].insn_type
-                           == ITYPE_LABEL))
-                      || i == istack.ninsn -1)
-                     && xtensa_opcode_is_jump (xtensa_default_isa,
-                                               tinsn->opcode) == 1
-                     && fragP->fr_next != NULL
-                     && ! fragP->fr_next->tc_frag_data.is_unreachable)
-                   {
-                     /* Create a new unreachable frag of zero size.  */
-                     size_t frag_size = sizeof (fragS);
-                     fragS *new_fragP = (fragS *) xmalloc (frag_size);
-                     memset (new_fragP, 0, frag_size);
-                     new_fragP->fr_address = fragP->fr_next->fr_address;
-                     new_fragP->fr_next = fragP->fr_next;
-                     new_fragP->fr_fix = 0;
-                     new_fragP->fr_var = 0;
-                     new_fragP->fr_type = rs_fill;
-                     new_fragP->tc_frag_data.is_unreachable = TRUE;
-                     /* The rest are zeros....  */
-                     /* Link it in to the chain.  */
-                     fragP->fr_next = new_fragP;
-                   }
-#endif
                }
              immed_instr += size;
              total_size += size;
                }
              immed_instr += size;
              total_size += size;
@@ -9607,9 +9363,6 @@ convert_frag_immed (segT segP,
       fragP->fr_fix += diff;
     }
 
       fragP->fr_fix += diff;
     }
 
-  /* Clean it up.  */
-  xg_free_vinsn (&orig_vinsn);
-
   /* Check for undefined immediates in LOOP instructions.  */
   if (is_loop)
     {
   /* Check for undefined immediates in LOOP instructions.  */
   if (is_loop)
     {
@@ -9698,7 +9451,7 @@ convert_frag_immed_finish_loop (segT segP, fragS *fragP, TInsn *tinsn)
   addressT addi_offset = 9;
   addressT addmi_offset = 12;
   fragS *next_fragP;
   addressT addi_offset = 9;
   addressT addmi_offset = 12;
   fragS *next_fragP;
-  size_t target_count;
+  int target_count;
 
   if (!insnbuf)
     insnbuf = xtensa_insnbuf_alloc (isa);
 
   if (!insnbuf)
     insnbuf = xtensa_insnbuf_alloc (isa);
@@ -9763,11 +9516,13 @@ convert_frag_immed_finish_loop (segT segP, fragS *fragP, TInsn *tinsn)
   tinsn_to_insnbuf (&addi_insn, insnbuf);
 
   fragP->tc_frag_data.is_insn = TRUE;
   tinsn_to_insnbuf (&addi_insn, insnbuf);
 
   fragP->tc_frag_data.is_insn = TRUE;
-  xtensa_insnbuf_to_chars (isa, insnbuf, fragP->fr_opcode + addi_offset, 0);
+  xtensa_insnbuf_to_chars
+    (isa, insnbuf, (unsigned char *) fragP->fr_opcode + addi_offset, 0);
 
   set_expr_const (&addmi_insn.tok[2], loop_length_hi);
   tinsn_to_insnbuf (&addmi_insn, insnbuf);
 
   set_expr_const (&addmi_insn.tok[2], loop_length_hi);
   tinsn_to_insnbuf (&addmi_insn, insnbuf);
-  xtensa_insnbuf_to_chars (isa, insnbuf, fragP->fr_opcode + addmi_offset, 0);
+  xtensa_insnbuf_to_chars
+    (isa, insnbuf, (unsigned char *) fragP->fr_opcode + addmi_offset, 0);
 
   /* Walk through all of the frags from here to the loop end
      and mark them as no_transform to keep them from being modified
 
   /* Walk through all of the frags from here to the loop end
      and mark them as no_transform to keep them from being modified
@@ -9899,38 +9654,6 @@ set_subseg_freq (segT seg, subsegT subseg, float total_f, float target_f)
 \f
 /* Segment Lists and emit_state Stuff.  */
 
 \f
 /* Segment Lists and emit_state Stuff.  */
 
-/* Remove the segment from the global sections list.  */
-
-static void
-xtensa_remove_section (segT sec)
-{
-  /* Handle brain-dead bfd_section_list_remove macro, which
-     expect the address of the prior section's "next" field, not
-     just the address of the section to remove.  */
-
-  segT *ps_next_ptr = &stdoutput->sections;
-  while (*ps_next_ptr != sec && *ps_next_ptr != NULL) 
-    ps_next_ptr = &(*ps_next_ptr)->next;
-  
-  assert (*ps_next_ptr != NULL);
-
-  bfd_section_list_remove (stdoutput, ps_next_ptr);
-}
-
-
-static void
-xtensa_insert_section (segT after_sec, segT sec)
-{
-  segT *after_sec_next;
-  if (after_sec == NULL)
-    after_sec_next = &stdoutput->sections;
-  else
-    after_sec_next = &after_sec->next;
-
-  bfd_section_list_insert (stdoutput, after_sec_next, sec);
-}
-
-
 static void
 xtensa_move_seg_list_to_beginning (seg_list *head)
 {
 static void
 xtensa_move_seg_list_to_beginning (seg_list *head)
 {
@@ -9941,9 +9664,11 @@ xtensa_move_seg_list_to_beginning (seg_list *head)
 
       /* Move the literal section to the front of the section list.  */
       assert (literal_section);
 
       /* Move the literal section to the front of the section list.  */
       assert (literal_section);
-      xtensa_remove_section (literal_section);
-      xtensa_insert_section (NULL, literal_section);
-
+      if (literal_section != stdoutput->sections)
+       {
+         bfd_section_list_remove (stdoutput, literal_section);
+         bfd_section_list_prepend (stdoutput, literal_section);
+       }
       head = head->next;
     }
 }
       head = head->next;
     }
 }
@@ -10010,17 +9735,15 @@ xtensa_move_literals (void)
            {
              literal_pool = search_frag->tc_frag_data.literal_frag;
              assert (literal_pool->fr_subtype == RELAX_LITERAL_POOL_BEGIN);
            {
              literal_pool = search_frag->tc_frag_data.literal_frag;
              assert (literal_pool->fr_subtype == RELAX_LITERAL_POOL_BEGIN);
-             /* Note that we set this fr_var to be a fix
-                chain when we created the literal pool location
-                as RELAX_LITERAL_POOL_BEGIN.  */
-             frchain_to = (frchainS *) literal_pool->fr_var;
+             frchain_to = literal_pool->tc_frag_data.lit_frchain;
+             assert (frchain_to);
            }
          insert_after = literal_pool;
 
          while (insert_after->fr_next->fr_subtype != RELAX_LITERAL_POOL_END)
            insert_after = insert_after->fr_next;
 
            }
          insert_after = literal_pool;
 
          while (insert_after->fr_next->fr_subtype != RELAX_LITERAL_POOL_END)
            insert_after = insert_after->fr_next;
 
-         dest_seg = (segT) insert_after->fr_next->fr_var;
+         dest_seg = insert_after->fr_next->tc_frag_data.lit_seg;
 
          *frag_splice = next_frag;
          search_frag->fr_next = insert_after->fr_next;
 
          *frag_splice = next_frag;
          search_frag->fr_next = insert_after->fr_next;
@@ -10086,7 +9809,7 @@ mark_literal_frags (seg_list *segment)
     {
       frchain_from = seg_info (segment->seg)->frchainP;
       search_frag = frchain_from->frch_root;
     {
       frchain_from = seg_info (segment->seg)->frchainP;
       search_frag = frchain_from->frch_root;
-      while (search_frag) 
+      while (search_frag)
        {
          search_frag->tc_frag_data.is_literal = TRUE;
          search_frag = search_frag->fr_next;
        {
          search_frag->tc_frag_data.is_literal = TRUE;
          search_frag = search_frag->fr_next;
@@ -10111,8 +9834,8 @@ xtensa_reorder_seg_list (seg_list *head, segT after)
       assert (literal_section);
       if (literal_section != after)
        {
       assert (literal_section);
       if (literal_section != after)
        {
-         xtensa_remove_section (literal_section);
-         xtensa_insert_section (after, literal_section);
+         bfd_section_list_remove (stdoutput, literal_section);
+         bfd_section_list_insert_after (stdoutput, after, literal_section);
        }
 
       head = head->next;
        }
 
       head = head->next;
@@ -10183,10 +9906,10 @@ xtensa_switch_to_non_abs_literal_fragment (emit_state *result)
 
   static bfd_boolean recursive = FALSE;
   fragS *pool_location = get_literal_pool_location (now_seg);
 
   static bfd_boolean recursive = FALSE;
   fragS *pool_location = get_literal_pool_location (now_seg);
-  bfd_boolean is_init = 
+  bfd_boolean is_init =
     (now_seg && !strcmp (segment_name (now_seg), INIT_SECTION_NAME));
 
     (now_seg && !strcmp (segment_name (now_seg), INIT_SECTION_NAME));
 
-  bfd_boolean is_fini = 
+  bfd_boolean is_fini =
     (now_seg && !strcmp (segment_name (now_seg), FINI_SECTION_NAME));
 
   if (pool_location == NULL
     (now_seg && !strcmp (segment_name (now_seg), FINI_SECTION_NAME));
 
   if (pool_location == NULL
@@ -10257,7 +9980,7 @@ xtensa_switch_section_emit_state (emit_state *state,
   state->now_subseg = now_subseg;
   state->generating_literals = generating_literals;
   generating_literals++;
   state->now_subseg = now_subseg;
   state->generating_literals = generating_literals;
   generating_literals++;
-  subseg_new (segment_name (new_now_seg), new_now_subseg);
+  subseg_set (new_now_seg, new_now_subseg);
 }
 
 
 }
 
 
@@ -10267,7 +9990,7 @@ static void
 xtensa_restore_emit_state (emit_state *state)
 {
   generating_literals = state->generating_literals;
 xtensa_restore_emit_state (emit_state *state)
 {
   generating_literals = state->generating_literals;
-  subseg_new (state->name, state->now_subseg);
+  subseg_set (state->now_seg, state->now_subseg);
 }
 
 
 }
 
 
@@ -10438,7 +10161,7 @@ xtensa_create_property_segments (frag_predicate property_function,
          xtensa_block_info *cur_block;
          /* This is a section with some data.  */
          int num_recs = 0;
          xtensa_block_info *cur_block;
          /* This is a section with some data.  */
          int num_recs = 0;
-         size_t rec_size;
+         bfd_size_type rec_size;
 
          for (cur_block = block; cur_block; cur_block = cur_block->next)
            num_recs++;
 
          for (cur_block = block; cur_block; cur_block = cur_block->next)
            num_recs++;
@@ -10455,7 +10178,7 @@ xtensa_create_property_segments (frag_predicate property_function,
            {
              /* Allocate a fragment and leak it.  */
              fragS *fragP;
            {
              /* Allocate a fragment and leak it.  */
              fragS *fragP;
-             size_t frag_size;
+             bfd_size_type frag_size;
              fixS *fixes;
              frchainS *frchainP;
              int i;
              fixS *fixes;
              frchainS *frchainP;
              int i;
@@ -10534,9 +10257,9 @@ xtensa_create_xproperty_segments (frag_flags_fn flag_fn,
       flagword flags;
 
       flags = bfd_get_section_flags (stdoutput, sec);
       flagword flags;
 
       flags = bfd_get_section_flags (stdoutput, sec);
-      if (flags & SEC_DEBUGGING)
-       continue;
-      if (!(flags & SEC_ALLOC))
+      if ((flags & SEC_DEBUGGING)
+         || !(flags & SEC_ALLOC)
+         || (flags & SEC_MERGE))
        continue;
 
       if (section_has_xproperty (sec, flag_fn))
        continue;
 
       if (section_has_xproperty (sec, flag_fn))
@@ -10570,7 +10293,7 @@ xtensa_create_xproperty_segments (frag_flags_fn flag_fn,
          xtensa_block_info *cur_block;
          /* This is a section with some data.  */
          int num_recs = 0;
          xtensa_block_info *cur_block;
          /* This is a section with some data.  */
          int num_recs = 0;
-         size_t rec_size;
+         bfd_size_type rec_size;
 
          for (cur_block = block; cur_block; cur_block = cur_block->next)
            num_recs++;
 
          for (cur_block = block; cur_block; cur_block = cur_block->next)
            num_recs++;
@@ -10588,7 +10311,7 @@ xtensa_create_xproperty_segments (frag_flags_fn flag_fn,
            {
              /* Allocate a fragment and (unfortunately) leak it.  */
              fragS *fragP;
            {
              /* Allocate a fragment and (unfortunately) leak it.  */
              fragS *fragP;
-             size_t frag_size;
+             bfd_size_type frag_size;
              fixS *fixes;
              frchainS *frchainP;
              int i;
              fixS *fixes;
              frchainS *frchainP;
              int i;
@@ -10666,18 +10389,7 @@ retrieve_segment_info (segT seg)
       seginfo->bfd_section = seg;
       seginfo->sym = 0;
       /* We will not be dealing with these, only our special ones.  */
       seginfo->bfd_section = seg;
       seginfo->sym = 0;
       /* We will not be dealing with these, only our special ones.  */
-#if 0
-      if (seg == bfd_abs_section_ptr)
-       abs_seg_info = seginfo;
-      else if (seg == bfd_und_section_ptr)
-       und_seg_info = seginfo;
-      else
-#endif
-       bfd_set_section_userdata (stdoutput, seg, (void *) seginfo);
-#if 0
-      seg_fix_rootP = &segment_info[seg].fix_root;
-      seg_fix_tailP = &segment_info[seg].fix_tail;
-#endif
+      bfd_set_section_userdata (stdoutput, seg, (void *) seginfo);
 
       frchainP = (frchainS *) xmalloc (sizeof (frchainS));
       frchainP->frch_root = NULL;
 
       frchainP = (frchainS *) xmalloc (sizeof (frchainS));
       frchainP->frch_root = NULL;
@@ -10963,7 +10675,7 @@ static bfd_vma
 xt_block_aligned_size (const xtensa_block_info *xt_block)
 {
   bfd_vma end_addr;
 xt_block_aligned_size (const xtensa_block_info *xt_block)
 {
   bfd_vma end_addr;
-  size_t align_bits;
+  unsigned align_bits;
 
   if (!xt_block->flags.is_align)
     return xt_block->size;
 
   if (!xt_block->flags.is_align)
     return xt_block->size;
@@ -11103,12 +10815,9 @@ init_op_placement_info_table (void)
       /* FIXME: Make tinsn allocation dynamic.  */
       if (xtensa_opcode_num_operands (isa, opcode) >= MAX_INSN_ARGS)
        as_fatal (_("too many operands in instruction"));
       /* FIXME: Make tinsn allocation dynamic.  */
       if (xtensa_opcode_num_operands (isa, opcode) >= MAX_INSN_ARGS)
        as_fatal (_("too many operands in instruction"));
-      opi->single = XTENSA_UNDEFINED;
-      opi->single_size = 0;
-      opi->widest = XTENSA_UNDEFINED;
-      opi->widest_size = 0;
       opi->narrowest = XTENSA_UNDEFINED;
       opi->narrowest_size = 0x7F;
       opi->narrowest = XTENSA_UNDEFINED;
       opi->narrowest_size = 0x7F;
+      opi->narrowest_slot = 0;
       opi->formats = 0;
       opi->num_formats = 0;
       opi->issuef = 0;
       opi->formats = 0;
       opi->num_formats = 0;
       opi->issuef = 0;
@@ -11128,20 +10837,7 @@ init_op_placement_info_table (void)
                    {
                      opi->narrowest = fmt;
                      opi->narrowest_size = fmt_length;
                    {
                      opi->narrowest = fmt;
                      opi->narrowest_size = fmt_length;
-                   }
-                 if (fmt_length > opi->widest_size)
-                   {
-                     opi->widest = fmt;
-                     opi->widest_size = fmt_length;
-                   }
-                 if (xtensa_format_num_slots (isa, fmt) == 1)
-                   {
-                     if (opi->single_size == 0
-                         || fmt_length < opi->single_size)
-                       {
-                         opi->single = fmt;
-                         opi->single_size = fmt_length;
-                       }
+                     opi->narrowest_slot = slot;
                    }
                }
            }
                    }
                }
            }
@@ -11165,15 +10861,21 @@ opcode_fits_format_slot (xtensa_opcode opcode, xtensa_format fmt, int slot)
 static int
 xg_get_single_size (xtensa_opcode opcode)
 {
 static int
 xg_get_single_size (xtensa_opcode opcode)
 {
-  assert (op_placement_table[opcode].single != XTENSA_UNDEFINED);
-  return op_placement_table[opcode].single_size;
+  return op_placement_table[opcode].narrowest_size;
 }
 
 
 static xtensa_format
 xg_get_single_format (xtensa_opcode opcode)
 {
 }
 
 
 static xtensa_format
 xg_get_single_format (xtensa_opcode opcode)
 {
-  return op_placement_table[opcode].single;
+  return op_placement_table[opcode].narrowest;
+}
+
+
+static int
+xg_get_single_slot (xtensa_opcode opcode)
+{
+  return op_placement_table[opcode].narrowest_slot;
 }
 
 \f
 }
 
 \f
@@ -11326,18 +11028,12 @@ tinsn_has_invalid_symbolic_operands (const TInsn *insn)
        default:
          /* Symbolic immediates are only allowed on the last immediate
             operand.  At this time, CONST16 is the only opcode where we
        default:
          /* Symbolic immediates are only allowed on the last immediate
             operand.  At this time, CONST16 is the only opcode where we
-            support non-PC-relative relocations.  (It isn't necessary
-            to complain about non-PC-relative relocations here, but
-            otherwise, no error is reported until the relocations are
-            generated, and the assembler won't get that far if there
-            are any other errors.  It's nice to see all the problems
-            at once.)  */
+            support non-PC-relative relocations.  */
          if (i != get_relaxable_immed (insn->opcode)
              || (xtensa_operand_is_PCrelative (isa, insn->opcode, i) != 1
                  && insn->opcode != xtensa_const16_opcode))
            {
          if (i != get_relaxable_immed (insn->opcode)
              || (xtensa_operand_is_PCrelative (isa, insn->opcode, i) != 1
                  && insn->opcode != xtensa_const16_opcode))
            {
-             as_bad (_("invalid symbolic operand %d on '%s'"),
-                     i, xtensa_opcode_name (isa, insn->opcode));
+             as_bad (_("invalid symbolic operand"));
              return TRUE;
            }
        }
              return TRUE;
            }
        }
@@ -11376,92 +11072,13 @@ tinsn_has_complex_operands (const TInsn *insn)
 }
 
 
 }
 
 
-/* Convert the constant operands in the tinsn to insnbuf.
-   Return TRUE if there is a symbol in the immediate field.
-
-   Before this is called,
-   1) the number of operands are correct
-   2) the tinsn is a ITYPE_INSN
-   3) ONLY the relaxable_ is built
-   4) All operands are O_constant, O_symbol.  All constants fit
-   The return value tells whether there are any remaining O_symbols.  */
-
-static bfd_boolean
-tinsn_to_insnbuf (TInsn *tinsn, xtensa_insnbuf insnbuf)
-{
-  static xtensa_insnbuf slotbuf = 0;
-  xtensa_isa isa = xtensa_default_isa;
-  xtensa_opcode opcode = tinsn->opcode;
-  xtensa_format fmt = xg_get_single_format (opcode);
-  bfd_boolean has_fixup = FALSE;
-  int noperands = xtensa_opcode_num_operands (isa, opcode);
-  int i;
-  uint32 opnd_value;
-  char *file_name;
-  int line;
-
-  if (!slotbuf)
-    slotbuf = xtensa_insnbuf_alloc (isa);
-
-  assert (tinsn->insn_type == ITYPE_INSN);
-  if (noperands != tinsn->ntok)
-    as_fatal (_("operand number mismatch"));
-
-  if (xtensa_opcode_encode (isa, fmt, 0, slotbuf, opcode))
-    as_fatal (_("cannot encode opcode"));
-
-  for (i = 0; i < noperands; ++i)
-    {
-      expressionS *expr = &tinsn->tok[i];
-      switch (expr->X_op)
-       {
-       case O_register:
-         if (xtensa_operand_is_visible (isa, opcode, i) == 0)
-           break;
-         /* The register number has already been checked in
-            expression_maybe_register, so we don't need to check here.  */
-         opnd_value = expr->X_add_number;
-         (void) xtensa_operand_encode (isa, opcode, i, &opnd_value);
-         xtensa_operand_set_field (isa, opcode, i, fmt, 0,
-                                   slotbuf, opnd_value);
-         break;
-
-       case O_constant:
-         if (xtensa_operand_is_visible (isa, opcode, i) == 0)
-           break;
-         as_where (&file_name, &line);
-         /* It is a constant and we called this function,
-            then we have to try to fit it.  */
-         xtensa_insnbuf_set_operand (slotbuf, fmt, 0, opcode, i,
-                                     expr->X_add_number, file_name, line);
-         break;
-
-       default:
-         has_fixup = TRUE;
-         break;
-       }
-    }
-
-  xtensa_format_encode (isa, fmt, insnbuf);
-  xtensa_format_set_slot (isa, fmt, 0, insnbuf, slotbuf);
-
-  return has_fixup;
-}
-
-
-/* Convert the constant operands in the tinsn to slotbuf.
-   Return TRUE if there is a symbol in the immediate field.
-   (Eventually this should replace tinsn_to_insnbuf.)  */
-
-/* Before this is called,
-   1) the number of operands are correct
-   2) the tinsn is a ITYPE_INSN
-   3) ONLY the relaxable_ is built
-   4) All operands are
-       O_constant, O_symbol
-      All constants fit
-
-   The return value tells whether there are any remaining O_symbols.  */
+/* Encode a TInsn opcode and its constant operands into slotbuf.
+   Return TRUE if there is a symbol in the immediate field.  This
+   function assumes that:
+   1) The number of operands are correct.
+   2) The insn_type is ITYPE_INSN.
+   3) The opcode can be encoded in the specified format and slot.
+   4) Operands are either O_constant or O_symbol, and all constants fit.  */
 
 static bfd_boolean
 tinsn_to_slotbuf (xtensa_format fmt,
 
 static bfd_boolean
 tinsn_to_slotbuf (xtensa_format fmt,
@@ -11475,8 +11092,6 @@ tinsn_to_slotbuf (xtensa_format fmt,
   int noperands = xtensa_opcode_num_operands (isa, opcode);
   int i;
 
   int noperands = xtensa_opcode_num_operands (isa, opcode);
   int i;
 
-  *((int *) &slotbuf[0]) = 0;
-  *((int *) &slotbuf[1]) = 0;
   assert (tinsn->insn_type == ITYPE_INSN);
   if (noperands != tinsn->ntok)
     as_fatal (_("operand number mismatch"));
   assert (tinsn->insn_type == ITYPE_INSN);
   if (noperands != tinsn->ntok)
     as_fatal (_("operand number mismatch"));
@@ -11491,7 +11106,8 @@ tinsn_to_slotbuf (xtensa_format fmt,
   for (i = 0; i < noperands; i++)
     {
       expressionS *expr = &tinsn->tok[i];
   for (i = 0; i < noperands; i++)
     {
       expressionS *expr = &tinsn->tok[i];
-      int rc, line;
+      int rc;
+      unsigned line;
       char *file_name;
       uint32 opnd_value;
 
       char *file_name;
       uint32 opnd_value;
 
@@ -11530,6 +11146,44 @@ tinsn_to_slotbuf (xtensa_format fmt,
 }
 
 
 }
 
 
+/* Encode a single TInsn into an insnbuf.  If the opcode can only be encoded
+   into a multi-slot instruction, fill the other slots with NOPs.
+   Return TRUE if there is a symbol in the immediate field.  See also the
+   assumptions listed for tinsn_to_slotbuf.  */
+
+static bfd_boolean
+tinsn_to_insnbuf (TInsn *tinsn, xtensa_insnbuf insnbuf)
+{
+  static xtensa_insnbuf slotbuf = 0;
+  static vliw_insn vinsn;
+  xtensa_isa isa = xtensa_default_isa;
+  bfd_boolean has_fixup = FALSE;
+  int i;
+
+  if (!slotbuf)
+    {
+      slotbuf = xtensa_insnbuf_alloc (isa);
+      xg_init_vinsn (&vinsn);
+    }
+
+  xg_clear_vinsn (&vinsn);
+
+  bundle_tinsn (tinsn, &vinsn);
+
+  xtensa_format_encode (isa, vinsn.format, insnbuf);
+
+  for (i = 0; i < vinsn.num_slots; i++)
+    {
+      /* Only one slot may have a fix-up because the rest contains NOPs.  */
+      has_fixup |=
+       tinsn_to_slotbuf (vinsn.format, i, &vinsn.slots[i], vinsn.slotbuf[i]);
+      xtensa_format_set_slot (isa, vinsn.format, i, insnbuf, vinsn.slotbuf[i]);
+    }
+
+  return has_fixup;
+}
+
+
 /* Check the instruction arguments.  Return TRUE on failure.  */
 
 static bfd_boolean
 /* Check the instruction arguments.  Return TRUE on failure.  */
 
 static bfd_boolean
@@ -11610,21 +11264,9 @@ tinsn_immed_from_frag (TInsn *tinsn, fragS *fragP, int slot)
     {
       opnum = get_relaxable_immed (opcode);
       assert (opnum >= 0);
     {
       opnum = get_relaxable_immed (opcode);
       assert (opnum >= 0);
-      if (fragP->tc_frag_data.slot_sub_symbols[slot])
-       {
-         set_expr_symbol_offset_diff
-           (&tinsn->tok[opnum],
-            fragP->tc_frag_data.slot_symbols[slot],
-            fragP->tc_frag_data.slot_sub_symbols[slot],
-            fragP->tc_frag_data.slot_offsets[slot]);
-       }
-      else
-       {
-         set_expr_symbol_offset
-           (&tinsn->tok[opnum],
-            fragP->tc_frag_data.slot_symbols[slot],
-            fragP->tc_frag_data.slot_offsets[slot]);
-       }
+      set_expr_symbol_offset (&tinsn->tok[opnum],
+                             fragP->tc_frag_data.slot_symbols[slot],
+                             fragP->tc_frag_data.slot_offsets[slot]);
     }
 }
 
     }
 }
 
@@ -11677,8 +11319,6 @@ xg_init_vinsn (vliw_insn *v)
 
   for (i = 0; i < MAX_SLOTS; i++)
     {
 
   for (i = 0; i < MAX_SLOTS; i++)
     {
-      tinsn_init (&v->slots[i]);
-      v->slots[i].opcode = XTENSA_UNDEFINED;
       v->slotbuf[i] = xtensa_insnbuf_alloc (isa);
       if (v->slotbuf[i] == NULL)
        as_fatal (_("out of memory"));
       v->slotbuf[i] = xtensa_insnbuf_alloc (isa);
       if (v->slotbuf[i] == NULL)
        as_fatal (_("out of memory"));
@@ -11690,6 +11330,9 @@ static void
 xg_clear_vinsn (vliw_insn *v)
 {
   int i;
 xg_clear_vinsn (vliw_insn *v)
 {
   int i;
+
+  memset (v, 0, offsetof (vliw_insn, insnbuf));
+
   v->format = XTENSA_UNDEFINED;
   v->num_slots = 0;
   v->inside_bundle = FALSE;
   v->format = XTENSA_UNDEFINED;
   v->num_slots = 0;
   v->inside_bundle = FALSE;
@@ -11698,10 +11341,7 @@ xg_clear_vinsn (vliw_insn *v)
     debug_type = xt_saved_debug_type;
 
   for (i = 0; i < MAX_SLOTS; i++)
     debug_type = xt_saved_debug_type;
 
   for (i = 0; i < MAX_SLOTS; i++)
-    {
-      memset (&v->slots[i], 0, sizeof (TInsn));
-      v->slots[i].opcode = XTENSA_UNDEFINED;
-    }
+    v->slots[i].opcode = XTENSA_UNDEFINED;
 }
 
 
 }
 
 
@@ -11709,7 +11349,7 @@ static bfd_boolean
 vinsn_has_specific_opcodes (vliw_insn *v)
 {
   int i;
 vinsn_has_specific_opcodes (vliw_insn *v)
 {
   int i;
-  
+
   for (i = 0; i < v->num_slots; i++)
     {
       if (v->slots[i].is_specific_opcode)
   for (i = 0; i < v->num_slots; i++)
     {
       if (v->slots[i].is_specific_opcode)
@@ -11729,17 +11369,8 @@ xg_free_vinsn (vliw_insn *v)
 }
 
 
 }
 
 
-/* Before this is called, we should have
-   filled out the following fields:
-
-   1) the number of operands for each opcode are correct
-   2) the tinsn in the slots are ITYPE_INSN
-   3) ONLY the relaxable_ is built
-   4) All operands are
-       O_constant, O_symbol
-      All constants fit
-
-   The return value tells whether there are any remaining O_symbols.  */
+/* Encode a vliw_insn into an insnbuf.  Return TRUE if there are any symbolic
+   operands.  See also the assumptions listed for tinsn_to_slotbuf.  */
 
 static bfd_boolean
 vinsn_to_insnbuf (vliw_insn *vinsn,
 
 static bfd_boolean
 vinsn_to_insnbuf (vliw_insn *vinsn,
@@ -11764,14 +11395,7 @@ vinsn_to_insnbuf (vliw_insn *vinsn,
 
       xtensa_format_set_slot (isa, fmt, slot,
                              insnbuf, vinsn->slotbuf[slot]);
 
       xtensa_format_set_slot (isa, fmt, slot,
                              insnbuf, vinsn->slotbuf[slot]);
-      /* tinsn_has_fixup tracks if there is a fixup at all.
-        record_fixup controls globally.  I.E., we use this
-        function from several places, some of which are after
-        fixups have already been recorded.  Finally,
-        tinsn->record_fixup controls based on the individual ops,
-        which may or may not need it based on the relaxation
-        requirements.  */
-      if (tinsn_has_fixup && record_fixup)
+      if (tinsn_has_fixup)
        {
          int i;
          xtensa_opcode opcode = tinsn->opcode;
        {
          int i;
          xtensa_opcode opcode = tinsn->opcode;
@@ -11788,48 +11412,35 @@ vinsn_to_insnbuf (vliw_insn *vinsn,
                case O_hi16:
                  if (get_relaxable_immed (opcode) == i)
                    {
                case O_hi16:
                  if (get_relaxable_immed (opcode) == i)
                    {
-                     if (tinsn->record_fix || expr->X_op != O_symbol)
+                     /* Add a fix record for the instruction, except if this
+                        function is being called prior to relaxation, i.e.,
+                        if record_fixup is false, and the instruction might
+                        be relaxed later.  */
+                     if (record_fixup
+                         || tinsn->is_specific_opcode
+                         || !xg_is_relaxable_insn (tinsn, 0))
                        {
                        {
-                         if (!xg_add_opcode_fix
-                             (tinsn, i, fmt, slot, expr, fragP,
-                              frag_offset - fragP->fr_literal))
-                           as_bad (_("instruction with constant operands does not fit"));
+                         xg_add_opcode_fix (tinsn, i, fmt, slot, expr, fragP,
+                                            frag_offset - fragP->fr_literal);
                        }
                      else
                        {
                        }
                      else
                        {
+                         if (expr->X_op != O_symbol)
+                           as_bad (_("invalid operand"));
                          tinsn->symbol = expr->X_add_symbol;
                          tinsn->offset = expr->X_add_number;
                        }
                    }
                  else
                          tinsn->symbol = expr->X_add_symbol;
                          tinsn->offset = expr->X_add_number;
                        }
                    }
                  else
-                   as_bad (_("invalid operand %d on '%s'"),
-                           i, xtensa_opcode_name (isa, opcode));
+                   as_bad (_("symbolic operand not allowed"));
                  break;
 
                case O_constant:
                case O_register:
                  break;
 
                  break;
 
                case O_constant:
                case O_register:
                  break;
 
-               case O_subtract:
-                 if (get_relaxable_immed (opcode) == i)
-                   {
-                     if (tinsn->record_fix)
-                         as_bad (_("invalid subtract operand"));
-                     else
-                       {
-                         tinsn->symbol = expr->X_add_symbol;
-                         tinsn->sub_symbol = expr->X_op_symbol;
-                         tinsn->offset = expr->X_add_number;
-                       }
-                   }
-                 else
-                   as_bad (_("invalid operand %d on '%s'"),
-                           i, xtensa_opcode_name (isa, opcode));
-                 break;
-
                default:
                default:
-                 as_bad (_("invalid expression for operand %d on '%s'"),
-                         i, xtensa_opcode_name (isa, opcode));
+                 as_bad (_("expression too complex"));
                  break;
                }
            }
                  break;
                }
            }
@@ -11855,7 +11466,7 @@ vinsn_from_chars (vliw_insn *vinsn, char *f)
       slotbuf = xtensa_insnbuf_alloc (isa);
     }
 
       slotbuf = xtensa_insnbuf_alloc (isa);
     }
 
-  xtensa_insnbuf_from_chars (isa, insnbuf, f, 0);
+  xtensa_insnbuf_from_chars (isa, insnbuf, (unsigned char *) f, 0);
   fmt = xtensa_format_decode (isa, insnbuf);
   if (fmt == XTENSA_UNDEFINED)
     as_fatal (_("cannot decode instruction format"));
   fmt = xtensa_format_decode (isa, insnbuf);
   if (fmt == XTENSA_UNDEFINED)
     as_fatal (_("cannot decode instruction format"));
@@ -11935,21 +11546,6 @@ set_expr_symbol_offset (expressionS *s, symbolS *sym, offsetT offset)
 }
 
 
 }
 
 
-/* Set the expression to symbol - minus_sym + offset.  */
-
-static void
-set_expr_symbol_offset_diff (expressionS *s,
-                            symbolS *sym,
-                            symbolS *minus_sym,
-                            offsetT offset)
-{
-  s->X_op = O_subtract;
-  s->X_add_symbol = sym;
-  s->X_op_symbol = minus_sym;  /* unused */
-  s->X_add_number = offset;
-}
-
-
 /* Return TRUE if the two expressions are equal.  */
 
 bfd_boolean
 /* Return TRUE if the two expressions are equal.  */
 
 bfd_boolean
This page took 0.078157 seconds and 4 git commands to generate.