* config/tc-xtensa.c (xg_assembly_relax): Comment termination rules.

(frag_format_size): Handle RELAX_IMMED_STEP3.
	(xtensa_relax_frag, md_convert_frag): Likewise.
	* config/tc-xtensa.h (xtensa_relax_statesE): Add RELAX_IMMED_STEP3.
	(RELAX_IMMED_MAXSTEPS): Adjust.
	* config/xtensa-relax.c (widen_spec_list): Add transitions from
	wide branches to branch-over-jumps.
	(build_transition): Handle wide branches in transition patterns.
This commit is contained in:
Bob Wilson 2007-06-22 18:44:50 +00:00
parent 184d813c13
commit b81bf389ec
4 changed files with 89 additions and 17 deletions

View File

@ -1,3 +1,14 @@
2007-06-22 Sterling Augustine <sterling@tensilica.com>
* config/tc-xtensa.c (xg_assembly_relax): Comment termination rules.
(frag_format_size): Handle RELAX_IMMED_STEP3.
(xtensa_relax_frag, md_convert_frag): Likewise.
* config/tc-xtensa.h (xtensa_relax_statesE): Add RELAX_IMMED_STEP3.
(RELAX_IMMED_MAXSTEPS): Adjust.
* config/xtensa-relax.c (widen_spec_list): Add transitions from
wide branches to branch-over-jumps.
(build_transition): Handle wide branches in transition patterns.
2007-06-22 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-i386.c (disp_size): New.

View File

@ -3498,7 +3498,33 @@ xg_expand_to_stack (IStack *istack, TInsn *insn, int lateral_steps)
/* Relax the assembly instruction at least "min_steps".
Return the number of steps taken. */
Return the number of steps taken.
For relaxation to correctly terminate, every relaxation chain must
terminate in one of two ways:
1. If the chain from one instruction to the next consists entirely of
single instructions, then the chain *must* handle all possible
immediates without failing. It must not ever fail because an
immediate is out of range. The MOVI.N -> MOVI -> L32R relaxation
chain is one example. L32R loads 32 bits, and there cannot be an
immediate larger than 32 bits, so it satisfies this condition.
Single instruction relaxation chains are as defined by
xg_is_single_relaxable_instruction.
2. Otherwise, the chain must end in a multi-instruction expansion: e.g.,
BNEZ.N -> BNEZ -> BNEZ.W15 -> BENZ.N/J
Strictly speaking, in most cases you can violate condition 1 and be OK
-- in particular when the last two instructions have the same single
size. But nevertheless, you should guarantee the above two conditions.
We could fix this so that single-instruction expansions correctly
terminate when they can't handle the range, but the error messages are
worse, and it actually turns out that in every case but one (18-bit wide
branches), you need a multi-instruction expansion to get the full range
anyway. And because 18-bit branches are handled identically to 15-bit
branches, there isn't any point in changing it. */
static int
xg_assembly_relax (IStack *istack,
@ -3511,12 +3537,9 @@ xg_assembly_relax (IStack *istack,
{
int steps_taken = 0;
/* assert (has no symbolic operands)
Some of its immeds don't fit.
Try to build a relaxed version.
This may go through a couple of stages
of single instruction transformations before
we get there. */
/* Some of its immeds don't fit. Try to build a relaxed version.
This may go through a couple of stages of single instruction
transformations before we get there. */
TInsn single_target;
TInsn current_insn;
@ -4384,7 +4407,8 @@ frag_format_size (const fragS *fragP)
/* If an instruction is about to grow, return the longer size. */
if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP1
|| fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP2)
|| fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP2
|| fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP3)
return 3;
if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
@ -8324,6 +8348,7 @@ xtensa_relax_frag (fragS *fragP, long stretch, int *stretched_p)
case RELAX_IMMED:
case RELAX_IMMED_STEP1:
case RELAX_IMMED_STEP2:
case RELAX_IMMED_STEP3:
/* Place the immediate. */
new_stretch += relax_frag_immed
(now_seg, fragP, stretch,
@ -9041,6 +9066,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragp)
case RELAX_IMMED:
case RELAX_IMMED_STEP1:
case RELAX_IMMED_STEP2:
case RELAX_IMMED_STEP3:
/* Place the immediate. */
convert_frag_immed
(sec, fragp,

View File

@ -131,18 +131,20 @@ enum xtensa_relax_statesE
RELAX_IMMED,
/* The last instruction in this fragment (at->fr_opcode) contains
the value defined by fr_symbol (fr_offset = 0). If the value
does not fit, use the specified expansion. This is similar to
"NARROW", except that these may not be expanded in order to align
code. */
an immediate or symbol. If the value does not fit, relax the
opcode using expansions from the relax table. */
RELAX_IMMED_STEP1,
/* The last instruction in this fragment (at->fr_opcode) contains a
literal. It has already been expanded at least 1 step. */
literal. It has already been expanded 1 step. */
RELAX_IMMED_STEP2,
/* The last instruction in this fragment (at->fr_opcode) contains a
literal. It has already been expanded at least 2 steps. */
literal. It has already been expanded 2 steps. */
RELAX_IMMED_STEP3,
/* The last instruction in this fragment (at->fr_opcode) contains a
literal. It has already been expanded 3 steps. */
RELAX_SLOTS,
/* There are instructions within the last VLIW instruction that need
@ -179,7 +181,7 @@ enum xtensa_relax_statesE
/* This is used as a stopper to bound the number of steps that
can be taken. */
#define RELAX_IMMED_MAXSTEPS (RELAX_IMMED_STEP2 - RELAX_IMMED)
#define RELAX_IMMED_MAXSTEPS (RELAX_IMMED_STEP3 - RELAX_IMMED)
struct xtensa_frag_type
{

View File

@ -247,7 +247,10 @@ struct string_pattern_pair_struct
addi.n a4, 0x1010
=> addi a4, 0x1010
=> addmi a4, 0x1010
=> addmi a4, 0x1000, addi a4, 0x10. */
=> addmi a4, 0x1000, addi a4, 0x10.
See the comments in xg_assembly_relax for some important details
regarding how these chains must be built. */
static string_pattern_pair widen_spec_list[] =
{
@ -380,6 +383,10 @@ static string_pattern_pair widen_spec_list[] =
{"bnez %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%LABEL;j %label;LABEL"},
{"beqz %as,%label", "bnez %as,%LABEL;j %label;LABEL"},
{"bnez %as,%label", "beqz %as,%LABEL;j %label;LABEL"},
{"WIDE.beqz %as,%label ? IsaUseDensityInstruction", "bnez.n %as,%LABEL;j %label;LABEL"},
{"WIDE.bnez %as,%label ? IsaUseDensityInstruction", "beqz.n %as,%LABEL;j %label;LABEL"},
{"WIDE.beqz %as,%label", "bnez %as,%LABEL;j %label;LABEL"},
{"WIDE.bnez %as,%label", "beqz %as,%LABEL;j %label;LABEL"},
/* Widening expect-taken branches. */
{"beqzt %as,%label ? IsaUsePredictedBranches", "bnez %as,%LABEL;j %label;LABEL"},
@ -415,6 +422,29 @@ static string_pattern_pair widen_spec_list[] =
{"bbc %as,%at,%label", "bbs %as,%at,%LABEL;j %label;LABEL"},
{"bbs %as,%at,%label", "bbc %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.bgez %as,%label", "bltz %as,%LABEL;j %label;LABEL"},
{"WIDE.bltz %as,%label", "bgez %as,%LABEL;j %label;LABEL"},
{"WIDE.beqi %as,%imm,%label", "bnei %as,%imm,%LABEL;j %label;LABEL"},
{"WIDE.bnei %as,%imm,%label", "beqi %as,%imm,%LABEL;j %label;LABEL"},
{"WIDE.bgei %as,%imm,%label", "blti %as,%imm,%LABEL;j %label;LABEL"},
{"WIDE.blti %as,%imm,%label", "bgei %as,%imm,%LABEL;j %label;LABEL"},
{"WIDE.bgeui %as,%imm,%label", "bltui %as,%imm,%LABEL;j %label;LABEL"},
{"WIDE.bltui %as,%imm,%label", "bgeui %as,%imm,%LABEL;j %label;LABEL"},
{"WIDE.bbci %as,%imm,%label", "bbsi %as,%imm,%LABEL;j %label;LABEL"},
{"WIDE.bbsi %as,%imm,%label", "bbci %as,%imm,%LABEL;j %label;LABEL"},
{"WIDE.beq %as,%at,%label", "bne %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.bne %as,%at,%label", "beq %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.bge %as,%at,%label", "blt %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.blt %as,%at,%label", "bge %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.bgeu %as,%at,%label", "bltu %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.bltu %as,%at,%label", "bgeu %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.bany %as,%at,%label", "bnone %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.bnone %as,%at,%label", "bany %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.ball %as,%at,%label", "bnall %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.bnall %as,%at,%label", "ball %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.bbc %as,%at,%label", "bbs %as,%at,%LABEL;j %label;LABEL"},
{"WIDE.bbs %as,%at,%label", "bbc %as,%at,%LABEL;j %label;LABEL"},
/* Expanding calls with literals. */
{"call0 %label,%ar0 ? IsaUseL32R",
"LITERAL %label; l32r a0,%LITERAL; callx0 a0,%ar0"},
@ -1571,7 +1601,10 @@ build_transition (insn_pattern *initial_insn,
precond_e *precond;
insn_repl_e *r;
opcode = xtensa_opcode_lookup (isa, initial_insn->t.opcode_name);
if (!wide_branch_opcode (initial_insn->t.opcode_name, ".w18", &opcode)
&& !wide_branch_opcode (initial_insn->t.opcode_name, ".w15", &opcode))
opcode = xtensa_opcode_lookup (isa, initial_insn->t.opcode_name);
if (opcode == XTENSA_UNDEFINED)
{
/* It is OK to not be able to translate some of these opcodes. */