aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog23
-rw-r--r--gas/config/tc-xtensa.c157
-rw-r--r--gas/config/tc-xtensa.h1
-rw-r--r--gas/config/xtensa-istack.h2
4 files changed, 70 insertions, 113 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 4da5073..77d896e 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,26 @@
+2006-01-31 Bob Wilson <bob.wilson@acm.org>
+
+ * config/xtensa-istack.h (TInsn): Remove record_fix and sub_symbol
+ fields.
+ * config/tc-xtensa.h (xtensa_frag_type): Remove slot_sub_symbols field.
+ * config/tc-xtensa.c (md_apply_fix): Check for unexpected uses of
+ subtracted symbols.
+ (relaxation_requirements): Add pfinish_frag argument and use it to
+ replace setting tinsn->record_fix fields.
+ (xg_assemble_vliw_tokens): Adjust calls to relaxation_requirements
+ and vinsn_to_insnbuf. Remove references to record_fix and
+ slot_sub_symbols fields.
+ (xtensa_mark_narrow_branches): Delete unused code.
+ (is_narrow_branch_guaranteed_in_range): Handle expr that is not just
+ a symbol.
+ (convert_frag_immed): Adjust vinsn_to_insnbuf call and do not set
+ record_fix fields.
+ (tinsn_immed_from_frag): Remove code for handling slot_sub_symbols.
+ (vinsn_to_insnbuf): Change use of record_fixup argument, replacing use
+ of the record_fix field. Simplify error messages for unexpected
+ symbolic operands.
+ (set_expr_symbol_offset_diff): Delete.
+
2006-01-31 Paul Brook <paul@codesourcery.com>
* config/tc-arm.c (arm_reg_parse): Check if reg is non-NULL.
diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
index 1efb7bd..e4d73bf 100644
--- a/gas/config/tc-xtensa.c
+++ b/gas/config/tc-xtensa.c
@@ -510,8 +510,6 @@ void set_expr_const (expressionS *, offsetT);
bfd_boolean expr_is_register (const expressionS *);
offsetT get_expr_register (const expressionS *);
void set_expr_symbol_offset (expressionS *, symbolS *, offsetT);
-static void set_expr_symbol_offset_diff
- (expressionS *, symbolS *, symbolS *, offsetT);
bfd_boolean expr_is_equal (expressionS *, expressionS *);
static void copy_expr (expressionS *, const expressionS *);
@@ -5537,12 +5535,19 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
char *const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
valueT val = 0;
+ /* Subtracted symbols are only allowed for a few relocation types, and
+ unless linkrelax is enabled, they should not make it to this point. */
+ if (fixP->fx_subsy && !(linkrelax && (fixP->fx_r_type == BFD_RELOC_32
+ || fixP->fx_r_type == BFD_RELOC_16
+ || fixP->fx_r_type == BFD_RELOC_8)))
+ as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
+
switch (fixP->fx_r_type)
{
case BFD_RELOC_32:
case BFD_RELOC_16:
case BFD_RELOC_8:
- if (linkrelax && fixP->fx_subsy)
+ if (fixP->fx_subsy)
{
switch (fixP->fx_r_type)
{
@@ -6460,8 +6465,9 @@ xg_find_narrowest_format (vliw_insn *vinsn)
each tinsn in the vinsn. */
static int
-relaxation_requirements (vliw_insn *vinsn)
+relaxation_requirements (vliw_insn *vinsn, bfd_boolean *pfinish_frag)
{
+ bfd_boolean finish_frag = FALSE;
int extra_space = 0;
int slot;
@@ -6479,13 +6485,6 @@ relaxation_requirements (vliw_insn *vinsn)
/* Difference in bytes between narrow and wide insns... */
extra_space += 1;
tinsn->subtype = RELAX_NARROW;
- tinsn->record_fix = TRUE;
- break;
- }
- else
- {
- tinsn->record_fix = FALSE;
- /* No extra_space needed. */
}
}
else
@@ -6510,16 +6509,17 @@ relaxation_requirements (vliw_insn *vinsn)
tinsn->literal_space = max_literal_size;
tinsn->subtype = RELAX_IMMED;
- tinsn->record_fix = FALSE;
extra_space += max_size;
}
else
{
- tinsn->record_fix = TRUE;
- /* No extra space needed. */
+ /* A fix record will be added for this instruction prior
+ to relaxation, so make it end the frag. */
+ finish_frag = TRUE;
}
}
}
+ *pfinish_frag = finish_frag;
return extra_space;
}
@@ -6635,7 +6635,7 @@ total_frag_text_expansion (fragS *fragP)
static void
xg_assemble_vliw_tokens (vliw_insn *vinsn)
{
- bfd_boolean finish_frag = FALSE;
+ bfd_boolean finish_frag;
bfd_boolean is_jump = FALSE;
bfd_boolean is_branch = FALSE;
xtensa_isa isa = xtensa_default_isa;
@@ -6762,7 +6762,7 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
insn_size = xtensa_format_length (isa, vinsn->format);
- extra_space = relaxation_requirements (vinsn);
+ extra_space = relaxation_requirements (vinsn, &finish_frag);
/* vinsn_to_insnbuf will produce the error. */
if (vinsn->format != XTENSA_UNDEFINED)
@@ -6772,7 +6772,7 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
frag_now->tc_frag_data.is_insn = TRUE;
}
- vinsn_to_insnbuf (vinsn, f, frag_now, TRUE);
+ vinsn_to_insnbuf (vinsn, f, frag_now, FALSE);
if (vinsn->format == XTENSA_UNDEFINED)
return;
@@ -6790,7 +6790,6 @@ 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.literal_frags[slot] = tinsn->literal_frag;
if (tinsn->literal_space != 0)
@@ -6803,8 +6802,8 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
if (xtensa_opcode_is_branch (isa, tinsn->opcode) == 1)
is_branch = TRUE;
- if (tinsn->subtype || tinsn->symbol || tinsn->record_fix
- || tinsn->offset || tinsn->literal_frag || is_jump || is_branch)
+ if (tinsn->subtype || tinsn->symbol || tinsn->offset
+ || tinsn->literal_frag || is_jump || is_branch)
finish_frag = TRUE;
}
@@ -7038,15 +7037,10 @@ xtensa_mark_narrow_branches (void)
&& fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED)
{
vliw_insn vinsn;
- const expressionS *expr;
- symbolS *symbolP;
vinsn_from_chars (&vinsn, fragP->fr_opcode);
tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0);
- expr = &vinsn.slots[0].tok[1];
- symbolP = expr->X_add_symbol;
-
if (vinsn.num_slots == 1
&& xtensa_opcode_is_branch (xtensa_default_isa,
vinsn.slots[0].opcode)
@@ -7087,8 +7081,14 @@ is_narrow_branch_guaranteed_in_range (fragS *fragP, TInsn *tinsn)
{
const expressionS *expr = &tinsn->tok[1];
symbolS *symbolP = expr->X_add_symbol;
- fragS *target_frag = symbol_get_frag (symbolP);
offsetT max_distance = expr->X_add_number;
+ fragS *target_frag;
+
+ if (expr->X_op != O_symbol)
+ return FALSE;
+
+ target_frag = symbol_get_frag (symbolP);
+
max_distance += (S_GET_VALUE (symbolP) - target_frag->fr_address);
if (is_branch_jmp_to_next (tinsn, fragP))
return FALSE;
@@ -9198,7 +9198,7 @@ convert_frag_immed (segT segP,
build_nop (&cur_vinsn.slots[0], bytes);
fragP->fr_fix += fragP->tc_frag_data.text_expansion[0];
}
- vinsn_to_insnbuf (&cur_vinsn, fr_opcode, frag_now, FALSE);
+ vinsn_to_insnbuf (&cur_vinsn, fr_opcode, frag_now, TRUE);
xtensa_insnbuf_to_chars
(isa, cur_vinsn.insnbuf, (unsigned char *) fr_opcode, 0);
fragP->fr_var = 0;
@@ -9333,7 +9333,6 @@ convert_frag_immed (segT segP,
first = FALSE;
if (opcode_fits_format_slot (tinsn->opcode, fmt, slot))
{
- tinsn->record_fix = TRUE;
cur_vinsn.slots[slot] = *tinsn;
}
else
@@ -9341,7 +9340,6 @@ convert_frag_immed (segT segP,
cur_vinsn.slots[slot].opcode =
xtensa_format_slot_nop_opcode (isa, fmt, slot);
cur_vinsn.slots[slot].ntok = 0;
- cur_vinsn.slots[slot].record_fix = FALSE;
}
vinsn_to_insnbuf (&cur_vinsn, immed_instr, fragP, TRUE);
xtensa_insnbuf_to_chars (isa, cur_vinsn.insnbuf,
@@ -11042,12 +11040,7 @@ tinsn_has_invalid_symbolic_operands (const TInsn *insn)
default:
/* Symbolic immediates are only allowed on the last immediate
operand. At this time, CONST16 is the only opcode where we
- support non-PC-relative relocations. (It isn't necessary
- to complain about non-PC-relative relocations here, but
- otherwise, no error is reported until the relocations are
- generated, and the assembler won't get that far if there
- are any other errors. It's nice to see all the problems
- at once.) */
+ support non-PC-relative relocations. */
if (i != get_relaxable_immed (insn->opcode)
|| (xtensa_operand_is_PCrelative (isa, insn->opcode, i) != 1
&& insn->opcode != xtensa_const16_opcode))
@@ -11284,21 +11277,9 @@ tinsn_immed_from_frag (TInsn *tinsn, fragS *fragP, int slot)
{
opnum = get_relaxable_immed (opcode);
assert (opnum >= 0);
- if (fragP->tc_frag_data.slot_sub_symbols[slot])
- {
- set_expr_symbol_offset_diff
- (&tinsn->tok[opnum],
- fragP->tc_frag_data.slot_symbols[slot],
- fragP->tc_frag_data.slot_sub_symbols[slot],
- fragP->tc_frag_data.slot_offsets[slot]);
- }
- else
- {
- set_expr_symbol_offset
- (&tinsn->tok[opnum],
- fragP->tc_frag_data.slot_symbols[slot],
- fragP->tc_frag_data.slot_offsets[slot]);
- }
+ set_expr_symbol_offset (&tinsn->tok[opnum],
+ fragP->tc_frag_data.slot_symbols[slot],
+ fragP->tc_frag_data.slot_offsets[slot]);
}
}
@@ -11401,17 +11382,8 @@ xg_free_vinsn (vliw_insn *v)
}
-/* Before this is called, we should have
- filled out the following fields:
-
- 1) the number of operands for each opcode are correct
- 2) the tinsn in the slots are ITYPE_INSN
- 3) ONLY the relaxable_ is built
- 4) All operands are
- O_constant, O_symbol
- All constants fit
-
- The return value tells whether there are any remaining O_symbols. */
+/* Encode a vliw_insn into an insnbuf. Return TRUE if there are any symbolic
+ operands. See also the assumptions listed for tinsn_to_slotbuf. */
static bfd_boolean
vinsn_to_insnbuf (vliw_insn *vinsn,
@@ -11436,14 +11408,7 @@ vinsn_to_insnbuf (vliw_insn *vinsn,
xtensa_format_set_slot (isa, fmt, slot,
insnbuf, vinsn->slotbuf[slot]);
- /* tinsn_has_fixup tracks if there is a fixup at all.
- record_fixup controls globally. I.E., we use this
- function from several places, some of which are after
- fixups have already been recorded. Finally,
- tinsn->record_fixup controls based on the individual ops,
- which may or may not need it based on the relaxation
- requirements. */
- if (tinsn_has_fixup && record_fixup)
+ if (tinsn_has_fixup)
{
int i;
xtensa_opcode opcode = tinsn->opcode;
@@ -11460,48 +11425,35 @@ vinsn_to_insnbuf (vliw_insn *vinsn,
case O_hi16:
if (get_relaxable_immed (opcode) == i)
{
- if (tinsn->record_fix || expr->X_op != O_symbol)
+ /* Add a fix record for the instruction, except if this
+ function is being called prior to relaxation, i.e.,
+ if record_fixup is false, and the instruction might
+ be relaxed later. */
+ if (record_fixup
+ || tinsn->is_specific_opcode
+ || !xg_is_relaxable_insn (tinsn, 0))
{
- if (!xg_add_opcode_fix
- (tinsn, i, fmt, slot, expr, fragP,
- frag_offset - fragP->fr_literal))
- as_bad (_("instruction with constant operands does not fit"));
+ xg_add_opcode_fix (tinsn, i, fmt, slot, expr, fragP,
+ frag_offset - fragP->fr_literal);
}
else
{
+ if (expr->X_op != O_symbol)
+ as_bad (_("invalid operand"));
tinsn->symbol = expr->X_add_symbol;
tinsn->offset = expr->X_add_number;
}
}
else
- as_bad (_("invalid operand %d on '%s'"),
- i, xtensa_opcode_name (isa, opcode));
+ as_bad (_("symbolic operand not allowed"));
break;
case O_constant:
case O_register:
break;
- case O_subtract:
- if (get_relaxable_immed (opcode) == i)
- {
- if (tinsn->record_fix)
- as_bad (_("invalid subtract operand"));
- else
- {
- tinsn->symbol = expr->X_add_symbol;
- tinsn->sub_symbol = expr->X_op_symbol;
- tinsn->offset = expr->X_add_number;
- }
- }
- else
- as_bad (_("invalid operand %d on '%s'"),
- i, xtensa_opcode_name (isa, opcode));
- break;
-
default:
- as_bad (_("invalid expression for operand %d on '%s'"),
- i, xtensa_opcode_name (isa, opcode));
+ as_bad (_("expression too complex"));
break;
}
}
@@ -11607,21 +11559,6 @@ set_expr_symbol_offset (expressionS *s, symbolS *sym, offsetT offset)
}
-/* Set the expression to symbol - minus_sym + offset. */
-
-static void
-set_expr_symbol_offset_diff (expressionS *s,
- symbolS *sym,
- symbolS *minus_sym,
- offsetT offset)
-{
- s->X_op = O_subtract;
- s->X_add_symbol = sym;
- s->X_op_symbol = minus_sym; /* unused */
- s->X_add_number = offset;
-}
-
-
/* Return TRUE if the two expressions are equal. */
bfd_boolean
diff --git a/gas/config/tc-xtensa.h b/gas/config/tc-xtensa.h
index e32b496..71f1ebb 100644
--- a/gas/config/tc-xtensa.h
+++ b/gas/config/tc-xtensa.h
@@ -242,7 +242,6 @@ struct xtensa_frag_type
fragS *literal_frags[MAX_SLOTS];
enum xtensa_relax_statesE slot_subtypes[MAX_SLOTS];
symbolS *slot_symbols[MAX_SLOTS];
- symbolS *slot_sub_symbols[MAX_SLOTS];
offsetT slot_offsets[MAX_SLOTS];
/* The global aligner needs to walk backward through the list of
diff --git a/gas/config/xtensa-istack.h b/gas/config/xtensa-istack.h
index 248e73f..7d2471a 100644
--- a/gas/config/xtensa-istack.h
+++ b/gas/config/xtensa-istack.h
@@ -51,12 +51,10 @@ typedef struct tinsn_struct
struct fixP *fixup;
/* Filled out by relaxation_requirements: */
- bfd_boolean record_fix;
enum xtensa_relax_statesE subtype;
int literal_space;
/* Filled out by vinsn_to_insnbuf: */
symbolS *symbol;
- symbolS *sub_symbol;
offsetT offset;
fragS *literal_frag;
} TInsn;