aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2002-07-30 10:56:04 +0000
committerNick Clifton <nickc@redhat.com>2002-07-30 10:56:04 +0000
commit3d0c9500439485b931db67beb2071039a69ff048 (patch)
treec1c06b15974d2f0db2664fef7382f44f65011994
parent5ec4a8f31301e303c88a997205069237b9bbe29e (diff)
downloadfsf-binutils-gdb-3d0c9500439485b931db67beb2071039a69ff048.zip
fsf-binutils-gdb-3d0c9500439485b931db67beb2071039a69ff048.tar.gz
fsf-binutils-gdb-3d0c9500439485b931db67beb2071039a69ff048.tar.bz2
Add per-section and per-sub-section literal pools.
-rw-r--r--gas/ChangeLog14
-rw-r--r--gas/config/tc-arm.c240
-rw-r--r--gas/doc/c-arm.texi8
3 files changed, 145 insertions, 117 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 240606e..9ac2aa8 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,17 @@
+2002-07-30 Nick Clifton <nickc@redhat.com>
+
+ * config/tc-arm.c (struct literal_pool): Add fields to allow
+ multiple literal pools to be maintained.
+ (find_literal_pool): New function.
+ (find_or_make_literal_pool): New function.
+ (add_to_literal_pool): Use find_or_make_literal_pool.
+ (arm_s_text, arm_s_data, arm_s_section): Remove - no longer
+ needed.
+ (s_ltorg): Use find_literal_pool.
+ (arm_cleanup): Dump all literal pools.
+ * doc/c-arm.texi: Document new behaviour of only dumping literal
+ pools upon request.
+
2002-07-26 Alan Modra <amodra@bigpond.net.au>
* config/tc-ppc.c (ppc_set_cpu): Use PPC_OPCODE_64 as the default
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index a6bbba1..7bb094f 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -2061,9 +2061,6 @@ static void s_code PARAMS ((int));
static void s_force_thumb PARAMS ((int));
static void s_thumb_func PARAMS ((int));
static void s_thumb_set PARAMS ((int));
-static void arm_s_text PARAMS ((int));
-static void arm_s_data PARAMS ((int));
-static void arm_s_section PARAMS ((int));
#ifdef OBJ_ELF
static void s_arm_elf_cons PARAMS ((int));
#endif
@@ -2085,17 +2082,10 @@ const pseudo_typeS md_pseudo_table[] =
{ "even", s_even, 0 },
{ "ltorg", s_ltorg, 0 },
{ "pool", s_ltorg, 0 },
- /* Allow for the effect of section changes. */
- { "text", arm_s_text, 0 },
- { "data", arm_s_data, 0 },
- { "section", arm_s_section, 0 },
- { "section.s", arm_s_section, 0 },
- { "sect", arm_s_section, 0 },
- { "sect.s", arm_s_section, 0 },
#ifdef OBJ_ELF
{ "word", s_arm_elf_cons, 4 },
{ "long", s_arm_elf_cons, 4 },
- { "file", dwarf2_directive_file, 0 },
+ { "file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
{ "loc", dwarf2_directive_loc, 0 },
#else
{ "word", cons, 4},
@@ -2125,73 +2115,130 @@ static int arm_parse_fpu PARAMS ((char *));
symbolS * last_label_seen;
static int label_is_thumb_function_name = false;
-/* Literal stuff. */
+/* Literal Pool stuff. */
#define MAX_LITERAL_POOL_SIZE 1024
-typedef struct literalS
+/* Literal pool structure. Held on a per-section
+ and per-sub-section basis. */
+typedef struct literal_pool
{
- struct expressionS exp;
- struct arm_it * inst;
-} literalT;
+ expressionS literals [MAX_LITERAL_POOL_SIZE];
+ unsigned int next_free_entry;
+ unsigned int id;
+ symbolS * symbol;
+ segT section;
+ subsegT sub_section;
+ struct literal_pool * next;
+} literal_pool;
-literalT literals[MAX_LITERAL_POOL_SIZE];
+/* Pointer to a linked list of literal pools. */
+literal_pool * list_of_pools = NULL;
-/* Next free entry in the pool. */
-int next_literal_pool_place = 0;
+static literal_pool * find_literal_pool PARAMS ((void));
+static literal_pool * find_or_make_literal_pool PARAMS ((void));
-/* Next literal pool number. */
-int lit_pool_num = 1;
+static literal_pool *
+find_literal_pool ()
+{
+ literal_pool * pool;
+
+ for (pool = list_of_pools; pool != NULL; pool = pool->next)
+ {
+ if (pool->section == now_seg
+ && pool->sub_section == now_subseg)
+ break;
+ }
+
+ return pool;
+}
-symbolS * current_poolP = NULL;
+static literal_pool *
+find_or_make_literal_pool ()
+{
+ /* Next literal pool ID number. */
+ static unsigned int latest_pool_num = 1;
+ literal_pool * pool;
+
+ pool = find_literal_pool ();
+ if (pool == NULL)
+ {
+ /* Create a new pool. */
+ pool = (literal_pool *) xmalloc (sizeof (* pool));
+ if (! pool)
+ return NULL;
+
+ pool->next_free_entry = 0;
+ pool->section = now_seg;
+ pool->sub_section = now_subseg;
+ pool->next = list_of_pools;
+ pool->symbol = NULL;
+
+ /* Add it to the list. */
+ list_of_pools = pool;
+ }
+
+ /* New pools, and emptied pools, will have a NULL symbol. */
+ if (pool->symbol == NULL)
+ {
+ pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
+ (valueT) 0, &zero_address_frag);
+ pool->id = latest_pool_num ++;
+ }
+
+ /* Done. */
+ return pool;
+}
+
+/* Add the literal in the global 'inst'
+ structure to the relevent literal pool. */
static int
add_to_lit_pool ()
{
- int lit_count = 0;
+ literal_pool * pool;
+ unsigned int entry;
- if (current_poolP == NULL)
- current_poolP = symbol_create (FAKE_LABEL_NAME, undefined_section,
- (valueT) 0, &zero_address_frag);
+ pool = find_or_make_literal_pool ();
- /* Check if this literal value is already in the pool: */
- while (lit_count < next_literal_pool_place)
+ /* Check if this literal value is already in the pool. */
+ for (entry = 0; entry < pool->next_free_entry; entry ++)
{
- if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
- && inst.reloc.exp.X_op == O_constant
- && (literals[lit_count].exp.X_add_number
+ if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
+ && (inst.reloc.exp.X_op == O_constant)
+ && (pool->literals[entry].X_add_number
== inst.reloc.exp.X_add_number)
- && literals[lit_count].exp.X_unsigned == inst.reloc.exp.X_unsigned)
+ && (pool->literals[entry].X_unsigned
+ == inst.reloc.exp.X_unsigned))
break;
- if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
- && inst.reloc.exp.X_op == O_symbol
- && (literals[lit_count].exp.X_add_number
+ if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
+ && (inst.reloc.exp.X_op == O_symbol)
+ && (pool->literals[entry].X_add_number
== inst.reloc.exp.X_add_number)
- && (literals[lit_count].exp.X_add_symbol
+ && (pool->literals[entry].X_add_symbol
== inst.reloc.exp.X_add_symbol)
- && (literals[lit_count].exp.X_op_symbol
+ && (pool->literals[entry].X_op_symbol
== inst.reloc.exp.X_op_symbol))
- break;
-
- lit_count++;
+ break;
}
- if (lit_count == next_literal_pool_place) /* New entry. */
+ /* Do we need to create a new entry? */
+ if (entry == pool->next_free_entry)
{
- if (next_literal_pool_place >= MAX_LITERAL_POOL_SIZE)
+ if (entry >= MAX_LITERAL_POOL_SIZE)
{
- inst.error = _("literal pool overflow");
+ inst.error = _("Literal Pool Overflow");
return FAIL;
}
- literals[next_literal_pool_place].exp = inst.reloc.exp;
- lit_count = next_literal_pool_place++;
+ pool->literals[entry] = inst.reloc.exp;
+ pool->next_free_entry += 1;
}
- inst.reloc.exp.X_op = O_symbol;
- inst.reloc.exp.X_add_number = (lit_count) * 4 - 8;
- inst.reloc.exp.X_add_symbol = current_poolP;
+ inst.reloc.exp.X_op = O_symbol;
+ inst.reloc.exp.X_add_number = (entry) * 4 - 8;
+ inst.reloc.exp.X_add_symbol = pool->symbol;
return SUCCESS;
}
@@ -2353,10 +2400,14 @@ static void
s_ltorg (ignored)
int ignored ATTRIBUTE_UNUSED;
{
- int lit_count = 0;
+ unsigned int entry;
+ literal_pool * pool;
char sym_name[20];
- if (current_poolP == NULL)
+ pool = find_literal_pool ();
+ if (pool == NULL
+ || pool->symbol == NULL
+ || pool->next_free_entry == 0)
return;
/* Align pool as you have word accesses.
@@ -2366,24 +2417,25 @@ s_ltorg (ignored)
record_alignment (now_seg, 2);
- sprintf (sym_name, "$$lit_\002%x", lit_pool_num++);
+ sprintf (sym_name, "$$lit_\002%x", pool->id);
- symbol_locate (current_poolP, sym_name, now_seg,
+ symbol_locate (pool->symbol, sym_name, now_seg,
(valueT) frag_now_fix (), frag_now);
- symbol_table_insert (current_poolP);
+ symbol_table_insert (pool->symbol);
- ARM_SET_THUMB (current_poolP, thumb_mode);
+ ARM_SET_THUMB (pool->symbol, thumb_mode);
#if defined OBJ_COFF || defined OBJ_ELF
- ARM_SET_INTERWORK (current_poolP, support_interwork);
+ ARM_SET_INTERWORK (pool->symbol, support_interwork);
#endif
- while (lit_count < next_literal_pool_place)
+ for (entry = 0; entry < pool->next_free_entry; entry ++)
/* First output the expression in the instruction to the pool. */
- emit_expr (&(literals[lit_count++].exp), 4); /* .word */
+ emit_expr (&(pool->literals[entry]), 4); /* .word */
- next_literal_pool_place = 0;
- current_poolP = NULL;
+ /* Mark the pool as empty. */
+ pool->next_free_entry = 0;
+ pool->symbol = NULL;
}
/* Same as s_align_ptwo but align 0 => align 2. */
@@ -2550,55 +2602,6 @@ s_thumb_set (equiv)
#endif
}
-/* If we change section we must dump the literal pool first. */
-
-static void
-arm_s_text (ignore)
- int ignore;
-{
- if (now_seg != text_section)
- s_ltorg (0);
-
-#ifdef OBJ_ELF
- obj_elf_text (ignore);
-#else
- s_text (ignore);
-#endif
-}
-
-static void
-arm_s_data (ignore)
- int ignore;
-{
- if (flag_readonly_data_in_text)
- {
- if (now_seg != text_section)
- s_ltorg (0);
- }
- else if (now_seg != data_section)
- s_ltorg (0);
-
-#ifdef OBJ_ELF
- obj_elf_data (ignore);
-#else
- s_data (ignore);
-#endif
-}
-
-static void
-arm_s_section (ignore)
- int ignore;
-{
- s_ltorg (0);
-
-#ifdef OBJ_ELF
- obj_elf_section (ignore);
-#endif
-#ifdef OBJ_COFF
- obj_coff_section (ignore);
-#endif
-}
-
static void
opcode_select (width)
int width;
@@ -10254,10 +10257,10 @@ tc_gen_reloc (section, fixp)
case BFD_RELOC_ARM_LITERAL:
case BFD_RELOC_ARM_HWLITERAL:
- /* If this is called then the a literal has been referenced across
- a section boundary - possibly due to an implicit dump. */
+ /* If this is called then the a literal has
+ been referenced across a section boundary. */
as_bad_where (fixp->fx_file, fixp->fx_line,
- _("literal referenced across section boundary (Implicit dump?)"));
+ _("Literal referenced across section boundary"));
return NULL;
#ifdef OBJ_ELF
@@ -10504,8 +10507,9 @@ md_assemble (str)
-k Generate PIC code
-mthumb Start in Thumb mode
-mthumb-interwork Code supports ARM/Thumb interworking
+ -mimplicit-litpool-dump Dump literal pool on section change
- For now we will also provide support for
+ For now we will also provide support for:
-mapcs-32 32-bit Program counter
-mapcs-26 26-bit Program counter
@@ -11210,12 +11214,14 @@ cons_fix_new_arm (frag, where, size, exp)
void
arm_cleanup ()
{
- if (current_poolP == NULL)
- return;
+ literal_pool * pool;
- /* Put it at the end of text section. */
- subseg_set (text_section, 0);
- s_ltorg (0);
+ for (pool = list_of_pools; pool; pool = pool->next)
+ {
+ /* Put it at the end of the relevent section. */
+ subseg_set (pool->section, pool->sub_section);
+ s_ltorg (0);
+ }
}
void
diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi
index 022faa0..0b52370 100644
--- a/gas/doc/c-arm.texi
+++ b/gas/doc/c-arm.texi
@@ -340,6 +340,14 @@ way that the @code{.thumb_func} directive does.
This directive causes the current contents of the literal pool to be
dumped into the current section (which is assumed to be the .text
section) at the current location (aligned to a word boundary).
+@code{GAS} maintains a separate literal pool for each section and each
+sub-section. The @code{.ltorg} directive will only affect the literal
+pool of the current section and sub-section. At the end of assembly
+all remaining, un-empty literal pools will automatically be dumped.
+
+Note - older versions of @code{GAS} would dump the current literal
+pool any time a section change occurred. This is no longer done, since
+it prevents accurate control of the placement of literal pools.
@cindex @code{.pool} directive, ARM
@item .pool