aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJohn David Anglin <dave.anglin@nrc-cnrc.gc.ca>2003-10-29 21:44:16 +0000
committerJohn David Anglin <danglin@gcc.gnu.org>2003-10-29 21:44:16 +0000
commitcb4d476cf4ea3b6889efa676d23f64efb81ecb1e (patch)
tree3f9b013a36f8c65c1295068d6f7270904d4bc863 /gcc
parentc1aa3958b1832d2c728c6fc192ab78c3ea737c3b (diff)
downloadgcc-cb4d476cf4ea3b6889efa676d23f64efb81ecb1e.zip
gcc-cb4d476cf4ea3b6889efa676d23f64efb81ecb1e.tar.gz
gcc-cb4d476cf4ea3b6889efa676d23f64efb81ecb1e.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog23
-rw-r--r--gcc/config/pa/pa-linux.h4
-rw-r--r--gcc/config/pa/pa.c76
-rw-r--r--gcc/config/pa/pa.h61
4 files changed, 81 insertions, 83 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fddd65d..628b503 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/pa/pa-linux.h b/gcc/config/pa/pa-linux.h
index 027c946..2a714e3 100644
--- a/gcc/config/pa/pa-linux.h
+++ b/gcc/config/pa/pa-linux.h
@@ -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)
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 366128c..5e6d283 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -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. */
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 800c5df..37d3653 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -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)))