diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/config/pa/pa-linux.h | 4 | ||||
-rw-r--r-- | gcc/config/pa/pa.c | 76 | ||||
-rw-r--r-- | gcc/config/pa/pa.h | 61 |
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))) |