static bfd_boolean xtensa_is_littable_section (asection *);
static int internal_reloc_compare (const void *, const void *);
static int internal_reloc_matches (const void *, const void *);
-extern char *xtensa_get_property_section_name (asection *, const char *);
+extern asection *xtensa_get_property_section (asection *, const char *);
static flagword xtensa_get_property_predef_flags (asection *);
/* Other functions called directly by the linker. */
bfd_boolean output_addr)
{
asection *table_section;
- char *table_section_name;
bfd_size_type table_size = 0;
bfd_byte *table_data;
property_table_entry *blocks;
return 0;
}
- table_section_name = xtensa_get_property_section_name (section, sec_name);
- table_section = bfd_get_section_by_name (abfd, table_section_name);
- free (table_section_name);
+ table_section = xtensa_get_property_section (section, sec_name);
if (table_section)
table_size = table_section->size;
}
is_full_prop_section =
- ((strcmp (sec->name, XTENSA_PROP_SEC_NAME) == 0)
+ ((strncmp (sec->name, XTENSA_PROP_SEC_NAME,
+ sizeof (XTENSA_PROP_SEC_NAME) - 1) == 0)
|| (strncmp (sec->name, ".gnu.linkonce.prop.",
sizeof ".gnu.linkonce.prop." - 1) == 0));
}
-char *
-xtensa_get_property_section_name (asection *sec, const char *base_name)
+/* Predicate function used to look up a section in a particular group. */
+
+static bfd_boolean
+match_section_group (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
+{
+ const char *gname = inf;
+ const char *group_name = elf_group_name (sec);
+
+ return (group_name == gname
+ || (group_name != NULL
+ && gname != NULL
+ && strcmp (group_name, gname) == 0));
+}
+
+
+asection *
+xtensa_get_property_section (asection *sec, const char *base_name)
{
- if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0)
+ const char *suffix, *group_name;
+ char *prop_sec_name;
+ asection *prop_sec;
+
+ group_name = elf_group_name (sec);
+ if (group_name)
+ {
+ suffix = strrchr (sec->name, '.');
+ if (suffix == sec->name)
+ suffix = 0;
+ prop_sec_name = (char *) bfd_malloc (strlen (base_name) + 1
+ + (suffix ? strlen (suffix) : 0));
+ strcpy (prop_sec_name, base_name);
+ if (suffix)
+ strcat (prop_sec_name, suffix);
+ }
+ else if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0)
{
- char *prop_sec_name;
- const char *suffix;
char *linkonce_kind = 0;
if (strcmp (base_name, XTENSA_INSN_SEC_NAME) == 0)
if (strncmp (suffix, "t.", 2) == 0 && linkonce_kind[1] == '.')
suffix += 2;
strcat (prop_sec_name + linkonce_len, suffix);
+ }
+ else
+ prop_sec_name = strdup (base_name);
+
+ /* Check if the section already exists. */
+ prop_sec = bfd_get_section_by_name_if (sec->owner, prop_sec_name,
+ match_section_group,
+ (void *) group_name);
+ /* If not, create it. */
+ if (! prop_sec)
+ {
+ flagword flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY);
+ flags |= (bfd_get_section_flags (sec->owner, sec)
+ & (SEC_LINK_ONCE | SEC_LINK_DUPLICATES));
+
+ prop_sec = bfd_make_section_anyway_with_flags
+ (sec->owner, strdup (prop_sec_name), flags);
+ if (! prop_sec)
+ return 0;
- return prop_sec_name;
+ elf_group_name (prop_sec) = group_name;
}
- return strdup (base_name);
+ free (prop_sec_name);
+ return prop_sec;
}
flagword
xtensa_get_property_predef_flags (asection *sec)
{
- if (strcmp (sec->name, XTENSA_INSN_SEC_NAME) == 0
+ if (strncmp (sec->name, XTENSA_INSN_SEC_NAME,
+ sizeof (XTENSA_INSN_SEC_NAME) - 1) == 0
|| strncmp (sec->name, ".gnu.linkonce.x.",
sizeof ".gnu.linkonce.x." - 1) == 0)
return (XTENSA_PROP_INSN
#define LITERAL_SECTION_NAME xtensa_section_rename (".literal")
#define LIT4_SECTION_NAME xtensa_section_rename (".lit4")
-#define FINI_SECTION_NAME xtensa_section_rename (".fini")
#define INIT_SECTION_NAME xtensa_section_rename (".init")
-#define FINI_LITERAL_SECTION_NAME xtensa_section_rename (".fini.literal")
-#define INIT_LITERAL_SECTION_NAME xtensa_section_rename (".init.literal")
+#define FINI_SECTION_NAME xtensa_section_rename (".fini")
/* This type is used for the directive_stack to keep track of the
- state of the literal collection pools. */
+ state of the literal collection pools. If lit_prefix is set, it is
+ used to determine the literal section names; otherwise, the literal
+ sections are determined based on the current text section. The
+ lit_seg and lit4_seg fields cache these literal sections, with the
+ current_text_seg field used a tag to indicate whether the cached
+ values are valid. */
typedef struct lit_state_struct
{
- const char *lit_seg_name;
- const char *lit4_seg_name;
- const char *init_lit_seg_name;
- const char *fini_lit_seg_name;
+ char *lit_prefix;
+ segT current_text_seg;
segT lit_seg;
segT lit4_seg;
- segT init_lit_seg;
- segT fini_lit_seg;
} lit_state;
static lit_state default_lit_sections;
-/* We keep lists of literal segments. The seg_list type is the node
- for such a list. The *_literal_head locals are the heads of the
- various lists. All of these lists have a dummy node at the start. */
+/* We keep a list of literal segments. The seg_list type is the node
+ for this list. The literal_head pointer is the head of the list,
+ with the literal_head_h dummy node at the start. */
typedef struct seg_list_struct
{
static seg_list literal_head_h;
static seg_list *literal_head = &literal_head_h;
-static seg_list init_literal_head_h;
-static seg_list *init_literal_head = &init_literal_head_h;
-static seg_list fini_literal_head_h;
-static seg_list *fini_literal_head = &fini_literal_head_h;
/* Lists of symbols. We keep a list of symbols that label the current
static void xtensa_begin_directive (int);
static void xtensa_end_directive (int);
-static void xtensa_literal_prefix (char const *, int);
+static void xtensa_literal_prefix (void);
static void xtensa_literal_position (int);
static void xtensa_literal_pseudo (int);
static void xtensa_frequency_pseudo (int);
static void xtensa_switch_to_non_abs_literal_fragment (emit_state *);
static void xtensa_switch_section_emit_state (emit_state *, segT, subsegT);
static void xtensa_restore_emit_state (emit_state *);
-static void cache_literal_section
- (seg_list *, const char *, segT *, bfd_boolean);
+static segT cache_literal_section (bfd_boolean);
/* Import from elf32-xtensa.c in BFD library. */
-extern char *xtensa_get_property_section_name (asection *, const char *);
+extern asection *xtensa_get_property_section (asection *, const char *);
/* op_placement_info functions. */
directiveE directive;
bfd_boolean negated;
emit_state *state;
- int len;
lit_state *ls;
get_directive (&directive, &negated);
assert (ls);
*ls = default_lit_sections;
-
directive_push (directive_literal_prefix, negated, ls);
- /* Parse the new prefix from the input_line_pointer. */
- SKIP_WHITESPACE ();
- len = strspn (input_line_pointer,
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz_/0123456789.$");
-
/* Process the new prefix. */
- xtensa_literal_prefix (input_line_pointer, len);
-
- /* Skip the name in the input line. */
- input_line_pointer += len;
+ xtensa_literal_prefix ();
break;
case directive_freeregs:
/* Restore the default collection sections from saved state. */
s = (lit_state *) state;
assert (s);
-
default_lit_sections = *s;
- /* free the state storage */
+ /* Free the state storage. */
+ free (s->lit_prefix);
free (s);
break;
static void
-xtensa_literal_prefix (char const *start, int len)
+xtensa_literal_prefix (void)
{
- char *name, *linkonce_suffix;
- char *newname, *newname4;
- size_t linkonce_len;
+ char *name;
+ int len;
+
+ /* Parse the new prefix from the input_line_pointer. */
+ SKIP_WHITESPACE ();
+ len = strspn (input_line_pointer,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz_/0123456789.$");
/* Get a null-terminated copy of the name. */
name = xmalloc (len + 1);
assert (name);
-
- strncpy (name, start, len);
+ strncpy (name, input_line_pointer, len);
name[len] = 0;
- /* Allocate the sections (interesting note: the memory pointing to
- the name is actually used for the name by the new section). */
-
- newname = xmalloc (len + strlen (".literal") + 1);
- newname4 = xmalloc (len + strlen (".lit4") + 1);
-
- linkonce_len = sizeof (".gnu.linkonce.") - 1;
- if (strncmp (name, ".gnu.linkonce.", linkonce_len) == 0
- && (linkonce_suffix = strchr (name + linkonce_len, '.')) != 0)
- {
- strcpy (newname, ".gnu.linkonce.literal");
- strcpy (newname4, ".gnu.linkonce.lit4");
-
- strcat (newname, linkonce_suffix);
- strcat (newname4, linkonce_suffix);
- }
- else
- {
- int suffix_pos = len;
-
- /* If the section name ends with ".text", then replace that suffix
- instead of appending an additional suffix. */
- if (len >= 5 && strcmp (name + len - 5, ".text") == 0)
- suffix_pos -= 5;
+ /* Skip the name in the input line. */
+ input_line_pointer += len;
- strcpy (newname, name);
- strcpy (newname4, name);
+ default_lit_sections.lit_prefix = name;
- strcpy (newname + suffix_pos, ".literal");
- strcpy (newname4 + suffix_pos, ".lit4");
- }
-
- /* Note that cache_literal_section does not create a segment if
- it already exists. */
+ /* Clear cached literal sections, since the prefix has changed. */
default_lit_sections.lit_seg = NULL;
default_lit_sections.lit4_seg = NULL;
-
- /* Canonicalizing section names allows renaming literal
- sections to occur correctly. */
- default_lit_sections.lit_seg_name = tc_canonicalize_symbol_name (newname);
- default_lit_sections.lit4_seg_name = tc_canonicalize_symbol_name (newname4);
-
- free (name);
}
/* Return TRUE if the section flags are marked linkonce
- or the name is .gnu.linkonce*. */
+ or the name is .gnu.linkonce.*. */
+
+static int linkonce_len = sizeof (".gnu.linkonce.") - 1;
static bfd_boolean
get_is_linkonce_section (bfd *abfd ATTRIBUTE_UNUSED, segT sec)
link_once_flags = (flags & SEC_LINK_ONCE);
/* Flags might not be set yet. */
- if (!link_once_flags)
- {
- static size_t len = sizeof ".gnu.linkonce.t.";
+ if (!link_once_flags
+ && strncmp (segment_name (sec), ".gnu.linkonce.", linkonce_len) == 0)
+ link_once_flags = SEC_LINK_ONCE;
- if (strncmp (segment_name (sec), ".gnu.linkonce.t.", len - 1) == 0)
- link_once_flags = SEC_LINK_ONCE;
- }
return (link_once_flags != 0);
}
linkrelax = 1;
- /* Set up the .literal, .fini.literal and .init.literal sections. */
+ /* Set up the literal sections. */
memset (&default_lit_sections, 0, sizeof (default_lit_sections));
- default_lit_sections.init_lit_seg_name = INIT_LITERAL_SECTION_NAME;
- default_lit_sections.fini_lit_seg_name = FINI_LITERAL_SECTION_NAME;
- default_lit_sections.lit_seg_name = LITERAL_SECTION_NAME;
- default_lit_sections.lit4_seg_name = LIT4_SECTION_NAME;
subseg_set (current_section, current_subsec);
sym_list *lit;
mark_literal_frags (literal_head->next);
- mark_literal_frags (init_literal_head->next);
- mark_literal_frags (fini_literal_head->next);
if (use_literal_section)
return;
- segment = literal_head->next;
- while (segment)
+ for (segment = literal_head->next; segment; segment = segment->next)
{
+ /* Keep the literals for .init and .fini in separate sections. */
+ if (!strcmp (segment_name (segment->seg), INIT_SECTION_NAME)
+ || !strcmp (segment_name (segment->seg), FINI_SECTION_NAME))
+ continue;
+
frchain_from = seg_info (segment->seg)->frchainP;
search_frag = frchain_from->frch_root;
literal_pool = NULL;
}
frchain_from->fix_tail = NULL;
xtensa_restore_emit_state (&state);
- segment = segment->next;
}
/* Now fix up the SEGMENT value for all the literal symbols. */
/* Now that we have the last section, push all the literal
sections to the end. */
xtensa_reorder_seg_list (literal_head, last_sec);
- xtensa_reorder_seg_list (init_literal_head, last_sec);
- xtensa_reorder_seg_list (fini_literal_head, last_sec);
/* Now perform the final error check. */
for (sec = stdoutput->sections; sec != NULL; sec = sec->next)
{
if (directive_state[directive_absolute_literals])
{
- cache_literal_section (0, default_lit_sections.lit4_seg_name,
- &default_lit_sections.lit4_seg, FALSE);
- xtensa_switch_section_emit_state (result,
- default_lit_sections.lit4_seg, 0);
+ segT lit4_seg = cache_literal_section (TRUE);
+ xtensa_switch_section_emit_state (result, lit4_seg, 0);
}
else
xtensa_switch_to_non_abs_literal_fragment (result);
static void
xtensa_switch_to_non_abs_literal_fragment (emit_state *result)
{
- /* 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. */
-
static bfd_boolean recursive = FALSE;
fragS *pool_location = get_literal_pool_location (now_seg);
+ segT lit_seg;
bfd_boolean is_init =
(now_seg && !strcmp (segment_name (now_seg), INIT_SECTION_NAME));
-
bfd_boolean is_fini =
(now_seg && !strcmp (segment_name (now_seg), FINI_SECTION_NAME));
&& !is_init && ! is_fini)
{
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;
}
- /* Special case: If we are in the ".fini" or ".init" section, then
- we will ALWAYS be generating to the ".fini.literal" and
- ".init.literal" sections. */
-
- if (is_init)
- {
- cache_literal_section (init_literal_head,
- default_lit_sections.init_lit_seg_name,
- &default_lit_sections.init_lit_seg, TRUE);
- xtensa_switch_section_emit_state (result,
- default_lit_sections.init_lit_seg, 0);
- }
- else if (is_fini)
- {
- cache_literal_section (fini_literal_head,
- default_lit_sections.fini_lit_seg_name,
- &default_lit_sections.fini_lit_seg, TRUE);
- xtensa_switch_section_emit_state (result,
- default_lit_sections.fini_lit_seg, 0);
- }
- else
- {
- cache_literal_section (literal_head,
- default_lit_sections.lit_seg_name,
- &default_lit_sections.lit_seg, TRUE);
- xtensa_switch_section_emit_state (result,
- default_lit_sections.lit_seg, 0);
- }
+ lit_seg = cache_literal_section (FALSE);
+ xtensa_switch_section_emit_state (result, lit_seg, 0);
if (!use_literal_section
&& !is_init && !is_fini
}
-/* Get a segment of a given name. If the segment is already
- present, return it; otherwise, create a new one. */
+/* Predicate function used to look up a section in a particular group. */
-static void
-cache_literal_section (seg_list *head,
- const char *name,
- segT *pseg,
- bfd_boolean is_code)
+static bfd_boolean
+match_section_group (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
{
- segT current_section = now_seg;
- int current_subsec = now_subseg;
- segT seg;
+ const char *gname = inf;
+ const char *group_name = elf_group_name (sec);
+
+ return (group_name == gname
+ || (group_name != NULL
+ && gname != NULL
+ && strcmp (group_name, gname) == 0));
+}
- if (*pseg != 0)
- return;
- /* Check if the named section exists. */
- for (seg = stdoutput->sections; seg; seg = seg->next)
+/* Get the literal section to be used for the current text section.
+ The result may be cached in the default_lit_sections structure. */
+
+static segT
+cache_literal_section (bfd_boolean use_abs_literals)
+{
+ const char *text_name, *group_name = 0;
+ char *base_name, *name, *suffix;
+ segT *pcached;
+ segT seg, current_section;
+ int current_subsec;
+ bfd_boolean linkonce = FALSE;
+
+ /* Save the current section/subsection. */
+ current_section = now_seg;
+ current_subsec = now_subseg;
+
+ /* Clear the cached values if they are no longer valid. */
+ if (now_seg != default_lit_sections.current_text_seg)
{
- if (!strcmp (segment_name (seg), name))
- break;
+ default_lit_sections.current_text_seg = now_seg;
+ default_lit_sections.lit_seg = NULL;
+ default_lit_sections.lit4_seg = NULL;
+ }
+
+ /* Check if the literal section is already cached. */
+ if (use_abs_literals)
+ pcached = &default_lit_sections.lit4_seg;
+ else
+ pcached = &default_lit_sections.lit_seg;
+
+ if (*pcached)
+ return *pcached;
+
+ text_name = default_lit_sections.lit_prefix;
+ if (! text_name || ! *text_name)
+ {
+ text_name = segment_name (current_section);
+ group_name = elf_group_name (current_section);
+ linkonce = (current_section->flags & SEC_LINK_ONCE) != 0;
+ }
+
+ base_name = use_abs_literals ? ".lit4" : ".literal";
+ if (group_name)
+ {
+ name = xmalloc (strlen (base_name) + strlen (group_name) + 2);
+ sprintf (name, "%s.%s", base_name, group_name);
+ }
+ else if (strncmp (text_name, ".gnu.linkonce.", linkonce_len) == 0)
+ {
+ suffix = strchr (text_name + linkonce_len, '.');
+
+ name = xmalloc (linkonce_len + strlen (base_name) + 1
+ + (suffix ? strlen (suffix) : 0));
+ strcpy (name, ".gnu.linkonce");
+ strcat (name, base_name);
+ if (suffix)
+ strcat (name, suffix);
+ linkonce = TRUE;
+ }
+ else
+ {
+ /* If the section name ends with ".text", then replace that suffix
+ instead of appending an additional suffix. */
+ size_t len = strlen (text_name);
+ if (len >= 5 && strcmp (text_name + len - 5, ".text") == 0)
+ len -= 5;
+
+ name = xmalloc (len + strlen (base_name) + 1);
+ strcpy (name, text_name);
+ strcpy (name + len, base_name);
}
- if (!seg)
+ /* Canonicalize section names to allow renaming literal sections.
+ The group name, if any, came from the current text section and
+ has already been canonicalized. */
+ name = tc_canonicalize_symbol_name (name);
+
+ seg = bfd_get_section_by_name_if (stdoutput, name, match_section_group,
+ (void *) group_name);
+ if (! seg)
{
- /* Create a new literal section. */
- seg = subseg_new (name, (subsegT) 0);
- if (head)
+ flagword flags;
+
+ seg = subseg_force_new (name, 0);
+
+ if (! use_abs_literals)
{
- /* Add the newly created literal segment to the specified list. */
+ /* Add the newly created literal segment to the list. */
seg_list *n = (seg_list *) xmalloc (sizeof (seg_list));
n->seg = seg;
- n->next = head->next;
- head->next = n;
+ n->next = literal_head->next;
+ literal_head->next = n;
}
- bfd_set_section_flags (stdoutput, seg, SEC_HAS_CONTENTS |
- SEC_READONLY | SEC_ALLOC | SEC_LOAD
- | (is_code ? SEC_CODE : SEC_DATA));
+
+ flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC | SEC_LOAD
+ | (linkonce ? (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD) : 0)
+ | (use_abs_literals ? SEC_DATA : SEC_CODE));
+
+ elf_group_name (seg) = group_name;
+
+ bfd_set_section_flags (stdoutput, seg, flags);
bfd_set_section_alignment (stdoutput, seg, 2);
}
- *pseg = seg;
+ *pcached = seg;
subseg_set (current_section, current_subsec);
+ return seg;
}
\f
static void xtensa_create_xproperty_segments
(frag_flags_fn, const char *, xt_section_type);
static segment_info_type *retrieve_segment_info (segT);
-static segT retrieve_xtensa_section (char *);
static bfd_boolean section_has_property (segT, frag_predicate);
static bfd_boolean section_has_xproperty (segT, frag_flags_fn);
static void add_xt_block_frags
xtensa_post_relax_hook (void)
{
xtensa_move_seg_list_to_beginning (literal_head);
- xtensa_move_seg_list_to_beginning (init_literal_head);
- xtensa_move_seg_list_to_beginning (fini_literal_head);
xtensa_find_unmarked_state_frags ();
if (section_has_property (sec, property_function))
{
- char *property_section_name =
- xtensa_get_property_section_name (sec, section_name_base);
- segT insn_sec = retrieve_xtensa_section (property_section_name);
+ segT insn_sec =
+ xtensa_get_property_section (sec, section_name_base);
segment_info_type *xt_seg_info = retrieve_segment_info (insn_sec);
xtensa_block_info **xt_blocks =
&xt_seg_info->tc_segment_info_data.blocks[sec_type];
if (section_has_xproperty (sec, flag_fn))
{
- char *property_section_name =
- xtensa_get_property_section_name (sec, section_name_base);
- segT insn_sec = retrieve_xtensa_section (property_section_name);
+ segT insn_sec =
+ xtensa_get_property_section (sec, section_name_base);
segment_info_type *xt_seg_info = retrieve_segment_info (insn_sec);
xtensa_block_info **xt_blocks =
&xt_seg_info->tc_segment_info_data.blocks[sec_type];
}
-static segT
-retrieve_xtensa_section (char *sec_name)
-{
- bfd *abfd = stdoutput;
- flagword flags, out_flags, link_once_flags;
- segT s;
-
- flags = bfd_get_section_flags (abfd, now_seg);
- link_once_flags = (flags & SEC_LINK_ONCE);
- if (link_once_flags)
- link_once_flags |= (flags & SEC_LINK_DUPLICATES);
- out_flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY | link_once_flags);
-
- s = bfd_make_section_old_way (abfd, sec_name);
- if (s == NULL)
- as_bad (_("could not create section %s"), sec_name);
- if (!bfd_set_section_flags (abfd, s, out_flags))
- as_bad (_("invalid flag combination on section %s"), sec_name);
-
- return s;
-}
-
-
static bfd_boolean
section_has_property (segT sec, frag_predicate property_function)
{
@kindex --text-section-literals
@kindex --no-text-section-literals
Control the treatment of literal pools. The default is
-@samp{--no-@-text-@-section-@-literals}, which places literals in a
-separate section in the output file. This allows the literal pool to be
+@samp{--no-@-text-@-section-@-literals}, which places literals in
+separate sections in the output file. This allows the literal pool to be
placed in a data RAM/ROM. With @samp{--text-@-section-@-literals}, the
literals are interspersed in the text section in order to keep them as
close as possible to their references. This may be necessary for large
@code{L32R} instructions in the text section. These options only affect
literals referenced via PC-relative @code{L32R} instructions; literals
for absolute mode @code{L32R} instructions are handled separately.
+@xref{Literal Directive, ,literal}.
@item --absolute-literals | --no-absolute-literals
@kindex --absolute-literals
@code{ENTRY} and @code{L32R} instructions; instead, the assembler puts
the data in a literal pool.
-Literal pools for absolute mode @code{L32R} instructions
-(@pxref{Absolute Literals Directive}) are placed in a separate
-@code{.lit4} section. By default literal pools for PC-relative mode
-@code{L32R} instructions are placed in a separate @code{.literal}
-section; however, when using the @samp{--text-@-section-@-literals}
+Literal pools are placed by default in separate literal sections;
+however, when using the @samp{--text-@-section-@-literals}
option (@pxref{Xtensa Options, ,Command Line Options}), the literal
-pools are placed in the current section. These text section literal
+pools for PC-relative mode @code{L32R} instructions
+are placed in the current section.@footnote{Literals for the
+@code{.init} and @code{.fini} sections are always placed in separate
+sections, even when @samp{--text-@-section-@-literals} is enabled.}
+These text section literal
pools are created automatically before @code{ENTRY} instructions and
manually after @samp{.literal_position} directives (@pxref{Literal
Position Directive, ,literal_position}). If there are no preceding
must be used to place the text section literal pools; otherwise,
@command{@value{AS}} will report an error.
+When literals are placed in separate sections, the literal section names
+are derived from the names of the sections where the literals are
+defined. The base literal section names are @code{.literal} for
+PC-relative mode @code{L32R} instructions and @code{.lit4} for absolute
+mode @code{L32R} instructions (@pxref{Absolute Literals Directive,
+,absolute-literals}). These base names are used for literals defined in
+the default @code{.text} section. For literals defined in other
+sections or within the scope of a @code{literal_prefix} directive
+(@pxref{Literal Prefix Directive, ,literal_prefix}), the following rules
+determine the literal section name:
+
+@enumerate
+@item
+If the current section is a member of a section group, the literal
+section name includes the group name as a suffix to the base
+@code{.literal} or @code{.lit4} name, with a period to separate the base
+name and group name. The literal section is also made a member of the
+group.
+
+@item
+If the current section name (or @code{literal_prefix} value) begins with
+``@code{.gnu.linkonce.@var{kind}.}'', the literal section name is formed
+by replacing ``@code{.@var{kind}}'' with the base @code{.literal} or
+@code{.lit4} name. For example, for literals defined in a section named
+@code{.gnu.linkonce.t.func}, the literal section will be
+@code{.gnu.linkonce.literal.func} or @code{.gnu.linkonce.lit4.func}.
+
+@item
+If the current section name (or @code{literal_prefix} value) ends with
+@code{.text}, the literal section name is formed by replacing that
+suffix with the base @code{.literal} or @code{.lit4} name. For example,
+for literals defined in a section named @code{.iram0.text}, the literal
+section will be @code{.iram0.literal} or @code{.iram0.lit4}.
+
+@item
+If none of the preceding conditions apply, the literal section name is
+formed by adding the base @code{.literal} or @code{.lit4} name as a
+suffix to the current section name (or @code{literal_prefix} value).
+@end enumerate
+
@node Literal Position Directive
@subsection literal_position
@cindex @code{literal_position} directive
@subsection literal_prefix
@cindex @code{literal_prefix} directive
-The @code{literal_prefix} directive allows you to specify different
-sections to hold literals from different portions of an assembly file.
-With this directive, a single assembly file can be used to generate code
-into multiple sections, including literals generated by the assembler.
+The @code{literal_prefix} directive allows you to override the default
+literal section names, which are derived from the names of the sections
+where the literals are defined.
@smallexample
.begin literal_prefix [@var{name}]
.end literal_prefix
@end smallexample
-By default the assembler places literal pools in sections separate from
-the instructions, using the default literal section names of
-@code{.literal} for PC-relative mode @code{L32R} instructions and
-@code{.lit4} for absolute mode @code{L32R} instructions (@pxref{Absolute
-Literals Directive}). The @code{literal_prefix} directive causes
-different literal sections to be used for the code inside the delimited
-region. The new literal sections are determined by including @var{name}
-as a prefix to the default literal section names. If the @var{name}
+For literals defined within the delimited region, the literal section
+names are derived from the @var{name} argument instead of the name of
+the current section. The rules used to derive the literal section names
+do not change. @xref{Literal Directive, ,literal}. If the @var{name}
argument is omitted, the literal sections revert to the defaults. This
directive has no effect when using the
@samp{--text-@-section-@-literals} option (@pxref{Xtensa Options,
,Command Line Options}).
-Except for two special cases, the assembler determines the new literal
-sections by simply prepending @var{name} to the default section names,
-resulting in @code{@var{name}.literal} and @code{@var{name}.lit4}
-sections. The @code{literal_prefix} directive is often used with the
-name of the current text section as the prefix argument. To facilitate
-this usage, the assembler uses special case rules when it recognizes
-@var{name} as a text section name. First, if @var{name} ends with
-@code{.text}, that suffix is not included in the literal section name.
-For example, if @var{name} is @code{.iram0.text}, then the literal
-sections will be @code{.iram0.literal} and @code{.iram0.lit4}. Second,
-if @var{name} begins with @code{.gnu.linkonce.t.}, then the literal
-section names are formed by replacing the @code{.t} substring with
-@code{.literal} and @code{.lit4}. For example, if @var{name} is
-@code{.gnu.linkonce.t.func}, the literal sections will be
-@code{.gnu.linkonce.literal.func} and @code{.gnu.linkonce.lit4.func}.
-
@node Absolute Literals Directive
@subsection absolute-literals
@cindex @code{absolute-literals} directive