/* tc-xtensa.c -- Assemble Xtensa instructions.
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003-2017 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
/* Flags to indicate whether the hardware supports the density and
absolute literals options. */
-bfd_boolean density_supported = XCHAL_HAVE_DENSITY;
-bfd_boolean absolute_literals_supported = XSHAL_USE_ABSOLUTE_LITERALS;
+bfd_boolean density_supported;
+bfd_boolean absolute_literals_supported;
static vliw_insn cur_vinsn;
unsigned xtensa_num_pipe_stages;
-unsigned xtensa_fetch_width = XCHAL_INST_FETCH_WIDTH;
+unsigned xtensa_fetch_width;
static enum debug_info_type xt_saved_debug_type = DEBUG_NONE;
{
FALSE, /* none */
FALSE, /* literal */
-#if !XCHAL_HAVE_DENSITY
FALSE, /* density */
-#else
- TRUE, /* density */
-#endif
TRUE, /* transform */
FALSE, /* freeregs */
FALSE, /* longcalls */
FALSE, /* literal_prefix */
FALSE, /* schedule */
-#if XSHAL_USE_ABSOLUTE_LITERALS
- TRUE /* absolute_literals */
-#else
FALSE /* absolute_literals */
-#endif
};
/* A circular list of all potential and actual literal pool locations
if (!directive_state_stack)
{
- as_bad (_("unmatched end directive"));
+ as_bad (_("unmatched .end directive"));
*directive = directive_none;
return;
}
number_to_chars_littleendian (buf, val, n);
}
+static void
+xg_init_global_config (void)
+{
+ target_big_endian = XCHAL_HAVE_BE;
+
+ density_supported = XCHAL_HAVE_DENSITY;
+ absolute_literals_supported = XSHAL_USE_ABSOLUTE_LITERALS;
+ xtensa_fetch_width = XCHAL_INST_FETCH_WIDTH;
+
+ directive_state[directive_density] = XCHAL_HAVE_DENSITY;
+ directive_state[directive_absolute_literals] = XSHAL_USE_ABSOLUTE_LITERALS;
+}
+
+void
+xtensa_init (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
+{
+ xg_init_global_config ();
+}
/* This function is called once, at assembler startup time. It should
set up all the tables, etc. that the MD part of the assembler will
lps->seg = now_seg;
lps->frag_list.next = &lps->frag_list;
lps->frag_list.prev = &lps->frag_list;
+ /* Put candidate literal pool at the beginning of every section,
+ so that even when section starts with literal load there's a
+ literal pool available. */
+ lps->frag_count = auto_litpool_limit;
}
lps->frag_count++;
/* Move the fix-up from the original j insn to this one. */
fixP->fx_frag = fragP;
fixP->fx_where = fragP->fr_fix - 3;
+ fixP->fx_size = 3;
fixP->tc_fix_data.slot = 0;
+ fixP->fx_r_type = BFD_RELOC_XTENSA_SLOT0_OP;
xtensa_add_cached_fixup (&fixup_cache, fixP);
xtensa_format fmt;
xtensa_isa isa = xtensa_default_isa;
int growth = 0;
+ int i, slot = -1;
+
+ for (i = 0; i < MAX_SLOTS; ++i)
+ if (origfrag->tc_frag_data.slot_symbols[i])
+ {
+ gas_assert (slot == -1);
+ slot = i;
+ }
+
+ gas_assert (slot >= 0 && slot < MAX_SLOTS);
lsym = tramp->fr_symbol;
/* Assemble a jump to the target label in the trampoline frag. */
- tsym = origfrag->tc_frag_data.slot_symbols[0];
- toffset = origfrag-> tc_frag_data.slot_offsets[0];
+ tsym = origfrag->tc_frag_data.slot_symbols[slot];
+ toffset = origfrag-> tc_frag_data.slot_offsets[slot];
tinsn_init (&insn);
insn.insn_type = ITYPE_INSN;
insn.opcode = xtensa_j_opcode;
if (fixP)
fixP->fx_offset += 3;
/* Modify the original j to point here. */
- origfrag->tc_frag_data.slot_symbols[0] = lsym;
- origfrag->tc_frag_data.slot_offsets[0] = tramp->fr_fix - 3;
+ origfrag->tc_frag_data.slot_symbols[slot] = lsym;
+ origfrag->tc_frag_data.slot_offsets[slot] = tramp->fr_fix - 3;
/* If trampoline is full, remove it from the list. */
check_and_update_trampolines ();
static void mark_literal_frags (seg_list *);
+static void
+xg_promote_candidate_litpool (struct litpool_seg *lps,
+ struct litpool_frag *lp)
+{
+ fragS *poolbeg;
+ fragS *poolend;
+ symbolS *lsym;
+ char label[10 + 2 * sizeof (fragS *)];
+
+ poolbeg = lp->fragP;
+ lp->priority = 1;
+ poolbeg->fr_subtype = RELAX_LITERAL_POOL_BEGIN;
+ poolend = poolbeg->fr_next;
+ gas_assert (poolend->fr_type == rs_machine_dependent &&
+ poolend->fr_subtype == RELAX_LITERAL_POOL_END);
+ /* Create a local symbol pointing to the
+ end of the pool. */
+ sprintf (label, ".L0_LT_%p", poolbeg);
+ lsym = (symbolS *)local_symbol_make (label, lps->seg,
+ 0, poolend);
+ poolbeg->fr_symbol = lsym;
+ /* Rest is done in xtensa_relax_frag. */
+}
+
static void
xtensa_move_literals (void)
{
/* This is still a "candidate" but the next one
will be too far away, so revert to the nearest
one, convert it and add the jump around. */
- fragS *poolbeg;
- fragS *poolend;
- symbolS *lsym;
- char label[10 + 2 * sizeof (fragS *)];
lp = lpf->prev;
- poolbeg = lp->fragP;
- lp->priority = 1;
- poolbeg->fr_subtype = RELAX_LITERAL_POOL_BEGIN;
- poolend = poolbeg->fr_next;
- gas_assert (poolend->fr_type == rs_machine_dependent &&
- poolend->fr_subtype == RELAX_LITERAL_POOL_END);
- /* Create a local symbol pointing to the
- end of the pool. */
- sprintf (label, ".L0_LT_%p", poolbeg);
- lsym = (symbolS *)local_symbol_make (label, lps->seg,
- 0, poolend);
- poolbeg->fr_symbol = lsym;
- /* Rest is done in xtensa_relax_frag. */
+ break;
}
}
}
+
+ /* Convert candidate and add the jump around. */
+ if (lp->fragP->fr_subtype ==
+ RELAX_LITERAL_POOL_CANDIDATE_BEGIN)
+ xg_promote_candidate_litpool (lps, lp);
+
if (! litfrag->tc_frag_data.literal_frag)
{
/* Take earliest use of this literal to avoid
/* First, move the frag out of the literal section and
to the appropriate place. */
- /* Insert an aligmnent frag at start of pool. */
+ /* Insert an alignment frag at start of pool. */
if (literal_pool->fr_next->fr_type == rs_machine_dependent &&
literal_pool->fr_next->fr_subtype == RELAX_LITERAL_POOL_END)
{
static void
xtensa_switch_to_non_abs_literal_fragment (emit_state *result)
{
- static bfd_boolean recursive = FALSE;
fragS *pool_location = get_literal_pool_location (now_seg);
segT lit_seg;
bfd_boolean is_init =
if (pool_location == NULL
&& !use_literal_section
- && !recursive
&& !is_init && ! is_fini)
{
if (!auto_litpools)
{
as_bad (_("literal pool location required for text-section-literals; specify with .literal_position"));
}
-
- /* When we mark a literal pool location, we want to put a frag in
- the literal pool that points to it. But to do that, we want to
- switch_to_literal_fragment. But literal sections don't have
- literal pools, so their location is always null, so we would
- recurse forever. This is kind of hacky, but it works. */
-
- recursive = TRUE;
- xtensa_mark_literal_pool_location ();
- recursive = FALSE;
+ xtensa_maybe_create_literal_pool_frag (TRUE, TRUE);
+ pool_location = get_literal_pool_location (now_seg);
}
lit_seg = cache_literal_section (FALSE);