aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorBob Wilson <bob.wilson@acm.org>2005-03-26 00:21:01 +0000
committerBob Wilson <bob.wilson@acm.org>2005-03-26 00:21:01 +0000
commit7c834684b638b78f7f13161f8e5c8b81826d694c (patch)
treef92c08546cdfcf85d131c107db5e0f87e3e2b766 /gas/config
parent9d2f1968d45c9bdc74e057469d2184dea23d100b (diff)
downloadgdb-7c834684b638b78f7f13161f8e5c8b81826d694c.zip
gdb-7c834684b638b78f7f13161f8e5c8b81826d694c.tar.gz
gdb-7c834684b638b78f7f13161f8e5c8b81826d694c.tar.bz2
* config/tc-xtensa.c (use_longcalls): Delete.
(xg_symbolic_immeds_fit): Check for direct calls and return TRUE if the use_longcalls flag is set. Do this before checking the segment. (xg_expand_assembly_insn): Rearrange to use new do_expand flag. Never expand direct calls at this point. (xtensa_set_frag_assembly_state): Set use_longcalls flag. (xtensa_find_unmarked_state_frags): Likewise. (md_assemble): Do not disable longcalls by setting is_specific_opcode. (xg_assemble_vliw_tokens): Switch frags when use_longcalls changes. (convert_frag_immed): Remove unnecessary check of is_specific_opcode. * config/tc-xtensa.h (xtensa_frag_type): Add use_longcalls flag.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-xtensa.c121
-rw-r--r--gas/config/tc-xtensa.h1
2 files changed, 54 insertions, 68 deletions
diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
index 81e9886..0bebbd0 100644
--- a/gas/config/tc-xtensa.c
+++ b/gas/config/tc-xtensa.c
@@ -1031,16 +1031,6 @@ 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)
{
/* After md_end, you should be checking frag by frag, rather
@@ -3312,22 +3302,28 @@ xg_symbolic_immeds_fit (const TInsn *insn,
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)
+ if (pc_frag == 0
+ || xtensa_operand_is_PCrelative (isa, insn->opcode, i) == 0)
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;
- /* 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;
@@ -3645,7 +3641,7 @@ xg_assembly_relax (IStack *istack,
}
current_insn = *insn;
- /* Walk through all of the single instruction expansions. */
+ /* Walk through all of the single instruction expansions. */
while (xg_is_single_relaxable_insn (&current_insn))
{
int error_val = xg_expand_narrow (&single_target, &current_insn);
@@ -3943,15 +3939,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
- 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;
+ bfd_boolean do_expand;
+
memset (&new_insn, 0, sizeof (TInsn));
/* Narrow it if we can. xg_simplify_insn now does all the
@@ -3977,50 +3974,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. */
-
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 (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_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
- {
- 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;
}
@@ -4789,6 +4773,8 @@ xtensa_set_frag_assembly_state (fragS *fragP)
"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;
@@ -4847,6 +4833,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;
+ 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;
}
@@ -5300,11 +5288,6 @@ md_assemble (char *str)
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))
{
@@ -6760,6 +6743,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
+ || (directive_state[directive_longcalls]
+ != frag_now->tc_frag_data.use_longcalls)
|| (directive_state[directive_absolute_literals]
!= frag_now->tc_frag_data.use_absolute_literals)))
{
@@ -6877,9 +6862,9 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
{
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_sub_symbols[slot] = tinsn->sub_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);
@@ -9371,7 +9356,7 @@ convert_frag_immed (segT segP,
xtensa_insnbuf_to_chars (isa, orig_vinsn.insnbuf, fr_opcode, 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
diff --git a/gas/config/tc-xtensa.h b/gas/config/tc-xtensa.h
index e38fa6c..99032fd 100644
--- a/gas/config/tc-xtensa.h
+++ b/gas/config/tc-xtensa.h
@@ -195,6 +195,7 @@ struct xtensa_frag_type
unsigned int is_assembly_state_set : 1;
unsigned int is_no_density : 1;
unsigned int is_no_transform : 1;
+ unsigned int use_longcalls : 1;
unsigned int use_absolute_literals : 1;
/* Inhibits relaxation of machine-dependent alignment frags the