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
This commit is contained in:
committed by
John David Anglin
parent
c1aa3958b1
commit
cb4d476cf4
@@ -1,3 +1,26 @@
|
||||
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)
|
||||
|
||||
|
||||
+19
-53
@@ -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,
|
||||
label = XEXP (XVECEXP (pattern, 1, i), 0);
|
||||
|
||||
However, that requires state and assumes that we look
|
||||
at insns in order.
|
||||
tmp = gen_short_jump (label);
|
||||
|
||||
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 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. */
|
||||
|
||||
+36
-27
@@ -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)
|
||||
/* 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. */
|
||||
/* 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_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 \
|
||||
#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 assembler line
|
||||
that says to advance the location counter
|
||||
to a multiple of 2**LOG bytes. */
|
||||
/* 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, "\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. */
|
||||
|
||||
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
|
||||
fprintf (FILE, "\t.align %d\n", (1<<(LOG)))
|
||||
|
||||
Reference in New Issue
Block a user