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> 2003-10-29 David Edelsohn <edelsohn@gnu.org>
* config/rs6000/rs6000.h (UNITS_PER_WORD): Revert to * config/rs6000/rs6000.h (UNITS_PER_WORD): Revert to
......
...@@ -121,14 +121,14 @@ Boston, MA 02111-1307, USA. */ ...@@ -121,14 +121,14 @@ Boston, MA 02111-1307, USA. */
#undef ASM_OUTPUT_ADDR_VEC_ELT #undef ASM_OUTPUT_ADDR_VEC_ELT
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
if (TARGET_BIG_SWITCH) \ 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 \ else \
fprintf (FILE, "\tb .L%d\n\tnop\n", VALUE) fprintf (FILE, "\tb .L%d\n\tnop\n", VALUE)
#undef ASM_OUTPUT_ADDR_DIFF_ELT #undef ASM_OUTPUT_ADDR_DIFF_ELT
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
if (TARGET_BIG_SWITCH) \ 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 \ else \
fprintf (FILE, "\tb .L%d\n\tnop\n", VALUE) fprintf (FILE, "\tb .L%d\n\tnop\n", VALUE)
......
...@@ -4319,8 +4319,8 @@ pa_adjust_insn_length (rtx insn, int length) ...@@ -4319,8 +4319,8 @@ pa_adjust_insn_length (rtx insn, int length)
/* Jumps inside switch tables which have unfilled delay slots need /* Jumps inside switch tables which have unfilled delay slots need
adjustment. */ adjustment. */
if (GET_CODE (insn) == JUMP_INSN if (GET_CODE (insn) == JUMP_INSN
&& simplejump_p (insn) && GET_CODE (pat) == PARALLEL
&& GET_MODE (insn) == SImode) && get_attr_type (insn) == TYPE_BTABLE_BRANCH)
return 4; return 4;
/* Millicode insn with an unfilled delay slot. */ /* Millicode insn with an unfilled delay slot. */
else if (GET_CODE (insn) == INSN else if (GET_CODE (insn) == INSN
...@@ -7848,7 +7848,8 @@ following_call (rtx insn) ...@@ -7848,7 +7848,8 @@ following_call (rtx insn)
The jump instructions within the table are special; we must be able 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 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 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 We also surround the jump table itself with BEGIN_BRTAB and END_BRTAB
insns. This serves two purposes, first it prevents jump.c from insns. This serves two purposes, first it prevents jump.c from
...@@ -7874,7 +7875,7 @@ pa_reorg (void) ...@@ -7874,7 +7875,7 @@ pa_reorg (void)
/* Find and explode all ADDR_VEC or ADDR_DIFF_VEC insns. */ /* Find and explode all ADDR_VEC or ADDR_DIFF_VEC insns. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{ {
rtx pattern, tmp, location; rtx pattern, tmp, location, label;
unsigned int length, i; unsigned int length, i;
/* Find an ADDR_VEC or ADDR_DIFF_VEC insn to explode. */ /* Find an ADDR_VEC or ADDR_DIFF_VEC insn to explode. */
...@@ -7900,57 +7901,17 @@ pa_reorg (void) ...@@ -7900,57 +7901,17 @@ pa_reorg (void)
location = NEXT_INSN (location); location = NEXT_INSN (location);
if (GET_CODE (pattern) == ADDR_VEC) if (GET_CODE (pattern) == ADDR_VEC)
{ label = XEXP (XVECEXP (pattern, 0, i), 0);
/* 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);
}
else else
{ label = XEXP (XVECEXP (pattern, 1, i), 0);
/* Emit the jump itself. */
tmp = gen_jump (XEXP (XVECEXP (pattern, 1, i), 0)); tmp = gen_short_jump (label);
tmp = emit_jump_insn_after (tmp, location);
JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 1, i), 0); /* Emit the jump itself. */
/* It is easy to rely on the branch table markers tmp = emit_jump_insn_after (tmp, location);
during assembly output to trigger the correct code JUMP_LABEL (tmp) = label;
for a switch table jump with an unfilled delay slot, LABEL_NUSES (label)++;
location = NEXT_INSN (location);
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);
}
/* Emit a BARRIER after the jump. */ /* Emit a BARRIER after the jump. */
emit_barrier_after (location); emit_barrier_after (location);
...@@ -7968,7 +7929,12 @@ pa_reorg (void) ...@@ -7968,7 +7929,12 @@ pa_reorg (void)
} }
else 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)) for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{ {
/* Find an ADDR_VEC insn. */ /* Find an ADDR_VEC insn. */
......
...@@ -1550,11 +1550,14 @@ do { \ ...@@ -1550,11 +1550,14 @@ do { \
#define FUNCTION_NAME_P(NAME) (*(NAME) == '@') #define FUNCTION_NAME_P(NAME) (*(NAME) == '@')
/* Specify the machine mode that this machine uses /* Specify the machine mode that this machine uses for the index in the
for the index in the tablejump instruction. */ tablejump instruction. For small tables, an element consists of a
#define CASE_VECTOR_MODE (TARGET_BIG_SWITCH ? TImode : DImode) 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
/* Jump tables must be 32 bit aligned, no matter the size of the element. */ 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 ADDR_VEC_ALIGN(ADDR_VEC) 2
/* Define this as 1 if `char' should by default be signed; else as 0. */ /* Define this as 1 if `char' should by default be signed; else as 0. */
...@@ -1724,35 +1727,41 @@ do { \ ...@@ -1724,35 +1727,41 @@ do { \
#define ASM_OUTPUT_ASCII(FILE, P, SIZE) \ #define ASM_OUTPUT_ASCII(FILE, P, SIZE) \
output_ascii ((FILE), (P), (SIZE)) output_ascii ((FILE), (P), (SIZE))
/* This is how to output an element of a case-vector that is absolute. /* Jump tables are always placed in the text section. Technically, it
Note that this method makes filling these branch delay slots is possible to put them in the readonly data section when -mbig-switch
impossible. */ 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 #define JUMP_TABLES_IN_TEXT_SECTION 1
/* This is how to output an element of a case-vector that is relative. /* This is how to output an element of a case-vector that is absolute. */
This must be defined correctly as it is used when generating PIC code.
I believe it safe to use the same definition as ASM_OUTPUT_ADDR_VEC_ELT #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
on the PA since ASM_OUTPUT_ADDR_VEC_ELT uses pc-relative jump instructions if (TARGET_BIG_SWITCH) \
rather than a table of absolute addresses. */ 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) \ #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
if (TARGET_BIG_SWITCH) \ 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); \ fprintf (FILE, "\t.word L$%04d-L$%04d\n", VALUE, REL); \
else \ else \
fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE) fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
/* This is how to output an assembler line /* This is how to output an assembler line that says to advance the
that says to advance the location counter location counter to a multiple of 2**LOG bytes. */
to a multiple of 2**LOG bytes. */
#define ASM_OUTPUT_ALIGN(FILE,LOG) \ #define ASM_OUTPUT_ALIGN(FILE,LOG) \
fprintf (FILE, "\t.align %d\n", (1<<(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