Commit cb4d476c by John David Anglin Committed by John David Anglin

pa-linux.h (ASM_OUTPUT_ADDR_VEC_ELT): Use label in big switch ELTs.

	* pa-linux.h (ASM_OUTPUT_ADDR_VEC_ELT): Use label in big switch ELTs.
	(ASM_OUTPUT_ADDR_DIFF_ELT): Use label difference in big switch ELTs.
	* pa.c (pa_adjust_insn_length): Check for btable branches using
	attribute TYPE_BTABLE_BRANCH.
	(pa_reorg): Simplify.
	* pa.h (CASE_VECTOR_MODE): Change big switch mode to SImode.
	(ASM_OUTPUT_ADDR_VEC_ELT): As above.
	(ASM_OUTPUT_ADDR_DIFF_ELT): As above.
	* pa.md (btable_branch): New instruction type.
	(in_branch_delay, in_nullified_branch_delay, in_call_delay): Disallow
	btable branches.
	(define_delay): Add btable branches to insn types that may have an
	insn in the delay position.
	(Z2, Z3): Add btable branch to list.
	Simplify unamed pattern set copy pic_label_operand to register.  Add
	PA 2.0 variant.
	(short_jump): New jump for use in branch tables.
	(casesi, casesi0): Revise for new branch table formats.
	(casesi32, casesi32p, casesi64p): New casesi patterns.
	(indirect_jump): Move.

From-SVN: r73064
parent c1aa3958
2003-10-29 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* pa-linux.h (ASM_OUTPUT_ADDR_VEC_ELT): Use label in big switch ELTs.
(ASM_OUTPUT_ADDR_DIFF_ELT): Use label difference in big switch ELTs.
* pa.c (pa_adjust_insn_length): Check for btable branches using
attribute TYPE_BTABLE_BRANCH.
(pa_reorg): Simplify.
* pa.h (CASE_VECTOR_MODE): Change big switch mode to SImode.
(ASM_OUTPUT_ADDR_VEC_ELT): As above.
(ASM_OUTPUT_ADDR_DIFF_ELT): As above.
* pa.md (btable_branch): New instruction type.
(in_branch_delay, in_nullified_branch_delay, in_call_delay): Disallow
btable branches.
(define_delay): Add btable branches to insn types that may have an
insn in the delay position.
(Z2, Z3): Add btable branch to list.
Simplify unamed pattern set copy pic_label_operand to register. Add
PA 2.0 variant.
(short_jump): New jump for use in branch tables.
(casesi, casesi0): Revise for new branch table formats.
(casesi32, casesi32p, casesi64p): New casesi patterns.
(indirect_jump): Move.
2003-10-29 David Edelsohn <edelsohn@gnu.org>
* config/rs6000/rs6000.h (UNITS_PER_WORD): Revert to
......
......@@ -121,14 +121,14 @@ Boston, MA 02111-1307, USA. */
#undef ASM_OUTPUT_ADDR_VEC_ELT
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
if (TARGET_BIG_SWITCH) \
fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldil LR'.L%d,%%r1\n\tbe RR'.L%d(%%sr4,%%r1)\n\tldw -16(%%r30),%%r1\n", VALUE, VALUE); \
fprintf (FILE, "\t.word .L%d\n", VALUE); \
else \
fprintf (FILE, "\tb .L%d\n\tnop\n", VALUE)
#undef ASM_OUTPUT_ADDR_DIFF_ELT
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
if (TARGET_BIG_SWITCH) \
fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldw T'.L%d(%%r19),%%r1\n\tbv %%r0(%%r1)\n\tldw -16(%%r30),%%r1\n", VALUE); \
fprintf (FILE, "\t.word .L%d-.L%d\n", VALUE, REL); \
else \
fprintf (FILE, "\tb .L%d\n\tnop\n", VALUE)
......
......@@ -4319,8 +4319,8 @@ pa_adjust_insn_length (rtx insn, int length)
/* Jumps inside switch tables which have unfilled delay slots need
adjustment. */
if (GET_CODE (insn) == JUMP_INSN
&& simplejump_p (insn)
&& GET_MODE (insn) == SImode)
&& GET_CODE (pat) == PARALLEL
&& get_attr_type (insn) == TYPE_BTABLE_BRANCH)
return 4;
/* Millicode insn with an unfilled delay slot. */
else if (GET_CODE (insn) == INSN
......@@ -7848,7 +7848,8 @@ following_call (rtx insn)
The jump instructions within the table are special; we must be able
to identify them during assembly output (if the jumps don't get filled
we need to emit a nop rather than nullifying the delay slot)). We
identify jumps in switch tables by marking the SET with DImode.
identify jumps in switch tables by using insns with the attribute
type TYPE_BTABLE_BRANCH.
We also surround the jump table itself with BEGIN_BRTAB and END_BRTAB
insns. This serves two purposes, first it prevents jump.c from
......@@ -7874,7 +7875,7 @@ pa_reorg (void)
/* Find and explode all ADDR_VEC or ADDR_DIFF_VEC insns. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
rtx pattern, tmp, location;
rtx pattern, tmp, location, label;
unsigned int length, i;
/* Find an ADDR_VEC or ADDR_DIFF_VEC insn to explode. */
......@@ -7900,57 +7901,17 @@ pa_reorg (void)
location = NEXT_INSN (location);
if (GET_CODE (pattern) == ADDR_VEC)
{
/* Emit the jump itself. */
tmp = gen_jump (XEXP (XVECEXP (pattern, 0, i), 0));
tmp = emit_jump_insn_after (tmp, location);
JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 0, i), 0);
/* It is easy to rely on the branch table markers
during assembly output to trigger the correct code
for a switch table jump with an unfilled delay slot,
However, that requires state and assumes that we look
at insns in order.
We can't make such assumptions when computing the length
of instructions. Ugh. We could walk the insn chain to
determine if this instruction is in a branch table, but
that can get rather expensive, particularly during the
branch shortening phase of the compiler.
So instead we mark this jump as being special. This is
far from ideal and knows that no code after this will
muck around with the mode of the JUMP_INSN itself. */
PUT_MODE (tmp, SImode);
LABEL_NUSES (JUMP_LABEL (tmp))++;
location = NEXT_INSN (location);
}
label = XEXP (XVECEXP (pattern, 0, i), 0);
else
{
/* Emit the jump itself. */
tmp = gen_jump (XEXP (XVECEXP (pattern, 1, i), 0));
tmp = emit_jump_insn_after (tmp, location);
JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 1, i), 0);
/* It is easy to rely on the branch table markers
during assembly output to trigger the correct code
for a switch table jump with an unfilled delay slot,
However, that requires state and assumes that we look
at insns in order.
We can't make such assumptions when computing the length
of instructions. Ugh. We could walk the insn chain to
determine if this instruction is in a branch table, but
that can get rather expensive, particularly during the
branch shortening phase of the compiler.
So instead we mark this jump as being special. This is
far from ideal and knows that no code after this will
muck around with the mode of the JUMP_INSN itself. */
PUT_MODE (tmp, SImode);
LABEL_NUSES (JUMP_LABEL (tmp))++;
location = NEXT_INSN (location);
}
label = XEXP (XVECEXP (pattern, 1, i), 0);
tmp = gen_short_jump (label);
/* Emit the jump itself. */
tmp = emit_jump_insn_after (tmp, location);
JUMP_LABEL (tmp) = label;
LABEL_NUSES (label)++;
location = NEXT_INSN (location);
/* Emit a BARRIER after the jump. */
emit_barrier_after (location);
......@@ -7968,7 +7929,12 @@ pa_reorg (void)
}
else
{
/* Sill need an end_brtab insn. */
/* Still need brtab marker insns. FIXME: the presence of these
markers disables output of the branch table to readonly memory,
and any alignment directives that might be needed. Possibly,
the begin_brtab insn should be output before the label for the
table. This doesn matter at the moment since the tables are
always output in the text section. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
/* Find an ADDR_VEC insn. */
......
......@@ -1550,11 +1550,14 @@ do { \
#define FUNCTION_NAME_P(NAME) (*(NAME) == '@')
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
#define CASE_VECTOR_MODE (TARGET_BIG_SWITCH ? TImode : DImode)
/* Jump tables must be 32 bit aligned, no matter the size of the element. */
/* Specify the machine mode that this machine uses for the index in the
tablejump instruction. For small tables, an element consists of a
ia-relative branch and its delay slot. When -mbig-switch is specified,
we use a 32-bit absolute address for non-pic code, and a 32-bit offset
for both 32 and 64-bit pic code. */
#define CASE_VECTOR_MODE (TARGET_BIG_SWITCH ? SImode : DImode)
/* Jump tables must be 32-bit aligned, no matter the size of the element. */
#define ADDR_VEC_ALIGN(ADDR_VEC) 2
/* Define this as 1 if `char' should by default be signed; else as 0. */
......@@ -1724,35 +1727,41 @@ do { \
#define ASM_OUTPUT_ASCII(FILE, P, SIZE) \
output_ascii ((FILE), (P), (SIZE))
/* This is how to output an element of a case-vector that is absolute.
Note that this method makes filling these branch delay slots
impossible. */
/* Jump tables are always placed in the text section. Technically, it
is possible to put them in the readonly data section when -mbig-switch
is specified. This has the benefit of getting the table out of .text
and reducing branch lengths as a result. The downside is that an
additional insn (addil) is needed to access the table when generating
PIC code. The address difference table also has to use 32-bit
pc-relative relocations. Currently, GAS does not support these
relocations, although it is easily modified to do this operation.
The table entries need to look like "$L1+(.+8-$L0)-$PIC_pcrel$0"
when using ELF GAS. A simple difference can be used when using
SOM GAS or the HP assembler. The final downside is GDB complains
about the nesting of the label for the table when debugging. */
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
if (TARGET_BIG_SWITCH) \
fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldil LR'L$%04d,%%r1\n\tbe RR'L$%04d(%%sr4,%%r1)\n\tldw -16(%%r30),%%r1\n", VALUE, VALUE); \
else \
fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
/* Jump tables are executable code and live in the TEXT section on the PA. */
#define JUMP_TABLES_IN_TEXT_SECTION 1
/* This is how to output an element of a case-vector that is relative.
This must be defined correctly as it is used when generating PIC code.
/* This is how to output an element of a case-vector that is absolute. */
I believe it safe to use the same definition as ASM_OUTPUT_ADDR_VEC_ELT
on the PA since ASM_OUTPUT_ADDR_VEC_ELT uses pc-relative jump instructions
rather than a table of absolute addresses. */
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
if (TARGET_BIG_SWITCH) \
fprintf (FILE, "\t.word L$%04d\n", VALUE); \
else \
fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
/* This is how to output an element of a case-vector that is relative.
Since we always place jump tables in the text section, the difference
is absolute and requires no relocation. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
if (TARGET_BIG_SWITCH) \
fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldw T'L$%04d(%%r19),%%r1\n\tbv %%r0(%%r1)\n\tldw -16(%%r30),%%r1\n", VALUE); \
else \
if (TARGET_BIG_SWITCH) \
fprintf (FILE, "\t.word L$%04d-L$%04d\n", VALUE, REL); \
else \
fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
/* This is how to output an assembler line
that says to advance the location counter
to a multiple of 2**LOG bytes. */
/* This is how to output an assembler line that says to advance the
location counter to a multiple of 2**LOG bytes. */
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
fprintf (FILE, "\t.align %d\n", (1<<(LOG)))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment