/* tc-xtensa.c -- Assemble Xtensa instructions.
- Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation, Inc.
+ Copyright (C) 2003-2014 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
-#include <limits.h>
#include "as.h"
+#include <limits.h>
#include "sb.h"
#include "safe-ctype.h"
#include "tc-xtensa.h"
md_flush_pending_output ();
- switch (end_directive)
+ switch ((int) end_directive)
{
- case (directiveE) XTENSA_UNDEFINED:
+ case XTENSA_UNDEFINED:
discard_rest_of_line ();
return;
- case directive_density:
+ case (int) directive_density:
as_warn (_(".end [no-]density is ignored"));
demand_empty_rest_of_line ();
break;
- case directive_absolute_literals:
+ case (int) directive_absolute_literals:
if (!absolute_literals_supported && !end_negated)
{
as_warn (_("Xtensa absolute literals option not supported; ignored"));
if (use_literal_section || directive_state[directive_absolute_literals])
dest_seg = now_seg;
+ /* FIXME, despite the previous comments, dest_seg is unused... */
+ (void) dest_seg;
+
/* All literals are aligned to four-byte boundaries. */
frag_align (2, 0, 0);
record_alignment (now_seg, 2);
}
+/* As specified in the relaxation table, when a loop instruction is
+ relaxed, there are 24 bytes between the loop instruction itself and
+ the first instruction in the loop. */
+
+#define RELAXED_LOOP_INSN_BYTES 24
+
static addressT
next_frag_pre_opcode_bytes (const fragS *fragp)
{
been relaxed. Note that we can assume that the LOOP
instruction is in slot 0 because loops aren't bundleable. */
if (next_fragp->tc_frag_data.slot_subtypes[0] > RELAX_IMMED)
- return get_expanded_loop_offset (next_opcode);
+ return get_expanded_loop_offset (next_opcode) + RELAXED_LOOP_INSN_BYTES;
return 0;
}
addressT frag_addr;
xtensa_format fmt;
- 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;
-
- if (frag_addr + op_size > xtensa_fetch_width)
- as_warn_where (frag->fr_file, frag->fr_line,
- _("unaligned loop: %d bytes at 0x%lx"),
- op_size, (long) frag->fr_address);
+ if (frag->fr_fix == 0)
+ frag = next_non_empty_frag (frag);
+
+ if (frag)
+ {
+ 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;
+
+ if (frag_addr + op_size > xtensa_fetch_width)
+ as_warn_where (frag->fr_file, frag->fr_line,
+ _("unaligned loop: %d bytes at 0x%lx"),
+ op_size, (long) frag->fr_address);
+ }
}
frag = frag->fr_next;
}
bfd_reloc_code_real_type reloc;
char *old_input_line_pointer;
expressionS *tok = &orig_insn.extra_arg;
- segT t;
old_input_line_pointer = input_line_pointer;
input_line_pointer = arg_strings[num_args - 1];
- t = expression (tok);
+ expression (tok);
if (tok->X_op == O_symbol
&& ((reloc = xtensa_elf_suffix (&input_line_pointer, tok))
== BFD_RELOC_XTENSA_TLS_CALL))
|| fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))
{
/* Find the loop frag. */
- fragS *targ_frag = next_non_empty_frag (fragP);
+ fragS *loop_frag = next_non_empty_frag (fragP);
/* Find the first insn frag. */
- targ_frag = next_non_empty_frag (targ_frag);
+ fragS *targ_frag = next_non_empty_frag (loop_frag);
+
+ /* Handle a corner case that comes up in hardware
+ diagnostics. The original assembly looks like this:
+
+ loop aX, LabelA
+ <empty_frag>--not found by next_non_empty_frag
+ loop aY, LabelB
+
+ Depending on the start address, the assembler may or
+ may not change it to look something like this:
+
+ loop aX, LabelA
+ nop--frag isn't empty anymore
+ loop aY, LabelB
+
+ So set up to check the alignment of the nop if it
+ exists */
+ while (loop_frag != targ_frag)
+ {
+ if (loop_frag->fr_type == rs_machine_dependent
+ && (loop_frag->fr_subtype == RELAX_ALIGN_NEXT_OPCODE
+ || loop_frag->fr_subtype
+ == RELAX_CHECK_ALIGN_NEXT_OPCODE))
+ targ_frag = loop_frag;
+ else
+ loop_frag = loop_frag->fr_next;
+ }
/* Of course, sometimes (mostly for toy test cases) a
zero-cost loop instruction is the last in a section. */
for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
{
fragS *fragP;
- fragS *current_target = NULL;
xtensa_opcode current_opcode = XTENSA_UNDEFINED;
/* Walk over all of the fragments in a subsection. */
TInsn t_insn;
fragS *loop_frag = next_non_empty_frag (fragP);
tinsn_from_chars (&t_insn, loop_frag->fr_opcode, 0);
- current_target = symbol_get_frag (fragP->fr_symbol);
current_opcode = t_insn.opcode;
gas_assert (xtensa_opcode_is_loop (xtensa_default_isa,
current_opcode) == 1);
(*widens)++;
break;
}
- address += total_frag_text_expansion (fragP);;
+ address += total_frag_text_expansion (fragP);
break;
case RELAX_IMMED:
symbolS *gen_label = NULL;
offsetT frag_offset;
bfd_boolean first = TRUE;
- bfd_boolean last_is_jump;
/* It does not fit. Find something that does and
convert immediately. */
total_size = 0;
first = TRUE;
- last_is_jump = FALSE;
for (i = 0; i < istack.ninsn; i++)
{
TInsn *tinsn = &istack.insn[i];
{
seg_list *segment;
frchainS *frchain_from, *frchain_to;
- fragS *search_frag, *next_frag, *last_frag, *literal_pool, *insert_after;
+ fragS *search_frag, *next_frag, *literal_pool, *insert_after;
fragS **frag_splice;
emit_state state;
segT dest_seg;
frags in it. */
frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
xtensa_set_frag_assembly_state (frag_now);
- last_frag = frag_now;
frag_variant (rs_fill, 0, 0, 0, NULL, 0, NULL);
xtensa_set_frag_assembly_state (frag_now);
}
else
{
- /* If the section name ends with ".text", then replace that suffix
- instead of appending an additional suffix. */
+ /* If the section name begins or ends with ".text", then replace
+ that portion instead of appending an additional suffix. */
size_t len = strlen (text_name);
- if (len >= 5 && strcmp (text_name + len - 5, ".text") == 0)
+ if (len >= 5
+ && (strcmp (text_name + len - 5, ".text") == 0
+ || strncmp (text_name, ".text", 5) == 0))
len -= 5;
name = xmalloc (len + strlen (base_name) + 1);
- strcpy (name, text_name);
- strcpy (name + len, base_name);
+ if (strncmp (text_name, ".text", 5) == 0)
+ {
+ strcpy (name, base_name);
+ strcat (name, text_name + 5);
+ }
+ else
+ {
+ strcpy (name, text_name);
+ strcpy (name + len, base_name);
+ }
}
/* Canonicalize section names to allow renaming literal sections.
void
istack_init (IStack *stack)
{
- memset (stack, 0, sizeof (IStack));
stack->ninsn = 0;
}