diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 8 | ||||
-rw-r--r-- | gas/config/tc-xtensa.c | 51 |
2 files changed, 38 insertions, 21 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 64b7a5e..884f0d9 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,11 @@ +2008-02-05 Sterling Augustine <sterling@tensilica.com> + + * config/tc-xtensa.c (relax_frag_immed): Change internal consistency + checks into assertions. When relaxation produces an operation that + does not fit in the current FLIX instruction, make sure that the + operation is relaxed as needed to account for being placed following + the current instruction. + 2008-02-04 H.J. Lu <hongjiu.lu@intel.com> PR 5715 diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index f18abd7..1321bfb 100644 --- a/gas/config/tc-xtensa.c +++ b/gas/config/tc-xtensa.c @@ -8997,9 +8997,8 @@ relax_frag_immed (segT segP, IStack istack; offsetT frag_offset; int num_steps; - fragS *lit_fragP; int num_text_bytes, num_literal_bytes; - int literal_diff, total_text_diff, this_text_diff, first; + int literal_diff, total_text_diff, this_text_diff; assert (fragP->fr_opcode != NULL); @@ -9038,36 +9037,46 @@ relax_frag_immed (segT segP, istack_init (&istack); num_steps = xg_assembly_relax (&istack, &tinsn, segP, fragP, frag_offset, min_steps, stretch); - if (num_steps < min_steps) - { - as_fatal (_("internal error: relaxation failed")); - return 0; - } - - if (num_steps > RELAX_IMMED_MAXSTEPS) - { - as_fatal (_("internal error: relaxation requires too many steps")); - return 0; - } + assert (num_steps >= min_steps && num_steps <= RELAX_IMMED_MAXSTEPS); fragP->tc_frag_data.slot_subtypes[slot] = (int) RELAX_IMMED + num_steps; /* Figure out the number of bytes needed. */ - lit_fragP = 0; num_literal_bytes = get_num_stack_literal_bytes (&istack); - literal_diff = - num_literal_bytes - fragP->tc_frag_data.literal_expansion[slot]; - first = 0; - while (istack.insn[first].opcode == XTENSA_UNDEFINED) - first++; - + literal_diff + = num_literal_bytes - fragP->tc_frag_data.literal_expansion[slot]; num_text_bytes = get_num_stack_text_bytes (&istack); if (from_wide_insn) { + int first = 0; + while (istack.insn[first].opcode == XTENSA_UNDEFINED) + first++; + num_text_bytes += old_size; if (opcode_fits_format_slot (istack.insn[first].opcode, fmt, slot)) num_text_bytes -= xg_get_single_size (istack.insn[first].opcode); + else + { + /* The first instruction in the relaxed sequence will go after + the current wide instruction, and thus its symbolic immediates + might not fit. */ + + istack_init (&istack); + num_steps = xg_assembly_relax (&istack, &tinsn, segP, fragP, + frag_offset + old_size, + min_steps, stretch + old_size); + assert (num_steps >= min_steps && num_steps <= RELAX_IMMED_MAXSTEPS); + + fragP->tc_frag_data.slot_subtypes[slot] + = (int) RELAX_IMMED + num_steps; + + num_literal_bytes = get_num_stack_literal_bytes (&istack); + literal_diff + = num_literal_bytes - fragP->tc_frag_data.literal_expansion[slot]; + + num_text_bytes = get_num_stack_text_bytes (&istack) + old_size; + } } total_text_diff = num_text_bytes - old_size; @@ -9086,7 +9095,7 @@ relax_frag_immed (segT segP, /* Find the associated expandable literal for this. */ if (literal_diff != 0) { - lit_fragP = fragP->tc_frag_data.literal_frags[slot]; + fragS *lit_fragP = fragP->tc_frag_data.literal_frags[slot]; if (lit_fragP) { assert (literal_diff == 4); |