2010-02-08 Sterling Augustine <sterling@tensilica.com>

* config/tc-xtensa.c (frag_format_size): Generalize logic to
	handle more instruction	sizes and fetch widths.
	(branch_align_power): Likewise.
	(text_align_power): Likewise.
	(bytes_to_stretch): Likewise.
This commit is contained in:
Sterling Augustine
2010-02-08 18:45:05 +00:00
parent 83b10087f4
commit 19ef5f3d6d
2 changed files with 116 additions and 140 deletions

View File

@ -1,9 +1,23 @@
2010-02-08 Sterling Augustine <sterling@tensilica.com>
* config/tc-xtensa.c (frag_format_size): Generalize logic to
handle more instruction sizes and fetch widths.
(branch_align_power): Likewise.
(text_align_power): Likewise.
(bytes_to_stretch): Likewise.
2010-02-08 Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
* config/tc-ppc.c (md_show_usage): Mention -mtitan. Don't use tabs.
(ppc_mach): Handle titan.
* doc/c-ppc.texi: Mention -mtitan.
2010-02-05 Sterling Augustine <sterling@tensilica.com>
* config/tc-xtensa.c (UNREACHABLE_MAX_WIDTH): Delete and
replace with...
(xtensa_fetch_width) ...this.
2010-02-05 Joseph Myers <joseph@codesourcery.com>
* Makefile.am (CPU_TYPES, OBJ_FORMATS, CPU_OBJ_VALID,

View File

@ -4521,12 +4521,18 @@ frag_format_size (const fragS *fragP)
be accompanied by major changes to make use of that data.
In any event, we can tell that we are expanding from a single-slot
three-byte format to a wider one with the logic below. */
format to a wider one with the logic below. */
if (fmt_size <= 3 && fragP->tc_frag_data.text_expansion[0] != 3)
return 3 + fragP->tc_frag_data.text_expansion[0];
else
return 3;
int i;
int relaxed_size = fmt_size + fragP->tc_frag_data.text_expansion[0];
for (i = 0; i < xtensa_isa_num_formats (isa); i++)
{
if (relaxed_size == xtensa_format_length (isa, i))
return relaxed_size;
}
return 3;
}
if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
@ -8226,8 +8232,33 @@ get_text_align_power (unsigned target_size)
{
if (target_size <= 4)
return 2;
gas_assert (target_size == 8);
return 3;
if (target_size <= 8)
return 3;
if (target_size <= 16)
return 4;
if (target_size <= 32)
return 5;
if (target_size <= 64)
return 6;
if (target_size <= 128)
return 7;
if (target_size <= 256)
return 8;
if (target_size <= 512)
return 9;
if (target_size <= 1024)
return 10;
gas_assert (0);
return 0;
}
@ -8300,19 +8331,17 @@ get_text_align_fill_size (addressT address,
static int
branch_align_power (segT sec)
{
/* If the Xtensa processor has a fetch width of 8 bytes, and the section
is aligned to at least an 8-byte boundary, then a branch target need
only fit within an 8-byte aligned block of memory to avoid a stall.
Otherwise, try to fit branch targets within 4-byte aligned blocks
(which may be insufficient, e.g., if the section has no alignment, but
it's good enough). */
if (xtensa_fetch_width == 8)
{
if (get_recorded_alignment (sec) >= 3)
return 3;
}
else
gas_assert (xtensa_fetch_width == 4);
/* If the Xtensa processor has a fetch width of X, and
the section is aligned to at least that boundary, then a branch
target need only fit within that aligned block of memory to avoid
a stall. Otherwise, try to fit branch targets within 4-byte
aligned blocks (which may be insufficient, e.g., if the section
has no alignment, but it's good enough). */
int fetch_align = get_text_align_power(xtensa_fetch_width);
int sec_align = get_recorded_alignment (sec);
if (sec_align >= fetch_align)
return fetch_align;
return 2;
}
@ -8976,39 +9005,11 @@ future_alignment_required (fragS *fragP, long stretch ATTRIBUTE_UNUSED)
/* The idea: widen everything you can to get a target or loop aligned,
then start using NOPs.
When we must have a NOP, here is a table of how we decide
(so you don't have to fight through the control flow below):
wide_nops = the number of wide NOPs available for aligning
narrow_nops = the number of narrow NOPs available for aligning
(a subset of wide_nops)
widens = the number of narrow instructions that should be widened
Desired wide narrow
Diff nop nop widens
1 0 0 1
2 0 1 0
3a 1 0 0
b 0 1 1 (case 3a makes this case unnecessary)
4a 1 0 1
b 0 2 0
c 0 1 2 (case 4a makes this case unnecessary)
5a 1 0 2
b 1 1 0
c 0 2 1 (case 5b makes this case unnecessary)
6a 2 0 0
b 1 0 3
c 0 1 4 (case 6b makes this case unnecessary)
d 1 1 1 (case 6a makes this case unnecessary)
e 0 2 2 (case 6a makes this case unnecessary)
f 0 3 0 (case 6a makes this case unnecessary)
7a 1 0 4
b 2 0 1
c 1 1 2 (case 7b makes this case unnecessary)
d 0 1 5 (case 7a makes this case unnecessary)
e 0 2 3 (case 7b makes this case unnecessary)
f 0 3 1 (case 7b makes this case unnecessary)
g 1 2 1 (case 7b makes this case unnecessary)
*/
static long
@ -9018,6 +9019,9 @@ bytes_to_stretch (fragS *this_frag,
int num_widens,
int desired_diff)
{
int nops_needed;
int nop_bytes;
int extra_bytes;
int bytes_short = desired_diff - num_widens;
gas_assert (desired_diff >= 0
@ -9048,100 +9052,58 @@ bytes_to_stretch (fragS *this_frag,
/* From here we will need at least one NOP to get an alignment.
However, we may not be able to align at all, in which case,
don't widen. */
if (this_frag->fr_subtype == RELAX_FILL_NOP)
{
switch (desired_diff)
{
case 1:
return 0;
case 2:
if (!this_frag->tc_frag_data.is_no_density && narrow_nops == 1)
return 2; /* case 2 */
return 0;
case 3:
if (wide_nops > 1)
return 0;
else
return 3; /* case 3a */
case 4:
if (num_widens >= 1 && wide_nops == 1)
return 3; /* case 4a */
if (!this_frag->tc_frag_data.is_no_density && narrow_nops == 2)
return 2; /* case 4b */
return 0;
case 5:
if (num_widens >= 2 && wide_nops == 1)
return 3; /* case 5a */
/* We will need two nops. Are there enough nops
between here and the align target? */
if (wide_nops < 2 || narrow_nops == 0)
return 0;
/* Are there other nops closer that can serve instead? */
if (wide_nops > 2 && narrow_nops > 1)
return 0;
/* Take the density one first, because there might not be
another density one available. */
if (!this_frag->tc_frag_data.is_no_density)
return 2; /* case 5b narrow */
else
return 3; /* case 5b wide */
return 0;
case 6:
if (wide_nops == 2)
return 3; /* case 6a */
else if (num_widens >= 3 && wide_nops == 1)
return 3; /* case 6b */
return 0;
case 7:
if (wide_nops == 1 && num_widens >= 4)
return 3; /* case 7a */
else if (wide_nops == 2 && num_widens >= 1)
return 3; /* case 7b */
return 0;
default:
gas_assert (0);
}
}
else
{
/* We will need a NOP no matter what, but should we widen
this instruction to help?
nops_needed = desired_diff / 3;
This is a RELAX_NARROW frag. */
switch (desired_diff)
{
case 1:
gas_assert (0);
return 0;
case 2:
case 3:
return 0;
case 4:
if (wide_nops >= 1 && num_widens == 1)
return 1; /* case 4a */
return 0;
case 5:
if (wide_nops >= 1 && num_widens == 2)
return 1; /* case 5a */
return 0;
case 6:
if (wide_nops >= 2)
return 0; /* case 6a */
else if (wide_nops >= 1 && num_widens == 3)
return 1; /* case 6b */
return 0;
case 7:
if (wide_nops >= 1 && num_widens == 4)
return 1; /* case 7a */
else if (wide_nops >= 2 && num_widens == 1)
return 1; /* case 7b */
return 0;
default:
gas_assert (0);
return 0;
}
/* If there aren't enough nops, don't widen. */
if (nops_needed > wide_nops)
return 0;
/* First try it with all wide nops. */
nop_bytes = nops_needed * 3;
extra_bytes = desired_diff - nop_bytes;
if (nop_bytes + num_widens >= desired_diff)
{
if (this_frag->fr_subtype == RELAX_FILL_NOP)
return 3;
else if (num_widens == extra_bytes)
return 1;
return 0;
}
gas_assert (0);
/* Add a narrow nop. */
nops_needed++;
nop_bytes += 2;
extra_bytes -= 2;
if (narrow_nops == 0 || nops_needed > wide_nops)
return 0;
if (nop_bytes + num_widens >= desired_diff && extra_bytes >= 0)
{
if (this_frag->fr_subtype == RELAX_FILL_NOP)
return !this_frag->tc_frag_data.is_no_density ? 2 : 3;
else if (num_widens == extra_bytes)
return 1;
return 0;
}
/* Replace a wide nop with a narrow nop--we can get here if
extra_bytes was negative in the previous conditional. */
if (narrow_nops == 1)
return 0;
nop_bytes--;
extra_bytes++;
if (nop_bytes + num_widens >= desired_diff)
{
if (this_frag->fr_subtype == RELAX_FILL_NOP)
return !this_frag->tc_frag_data.is_no_density ? 2 : 3;
else if (num_widens == extra_bytes)
return 1;
return 0;
}
/* If we can't satisfy any of the above cases, then we can't align
using padding or fill nops. */
return 0;
}