pa-linux.h (ASM_OUTPUT_ADDR_VEC_ELT): Use label in big switch ELTs.
authorJohn David Anglin <dave.anglin@nrc-cnrc.gc.ca>
Wed, 29 Oct 2003 21:44:16 +0000 (21:44 +0000)
committerJohn David Anglin <danglin@gcc.gnu.org>
Wed, 29 Oct 2003 21:44:16 +0000 (21:44 +0000)
* 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

gcc/ChangeLog
gcc/config/pa/pa-linux.h
gcc/config/pa/pa.c
gcc/config/pa/pa.h

index fddd65dafbbe84f1e40095d9177cd66411f1979f..628b5037c8689a88f1effde6d928292d8dcda9f2 100644 (file)
@@ -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
index 027c946dba3621a7c1df2d8a8690df7d15b83ff3..2a714e3ebdffd274c0eb2beb9d660229c1fcae68 100644 (file)
@@ -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)
 
index 366128c2c252254498a522c5dab2aa04726749a9..5e6d28383490192a601c88c77de57537bd2c7baf 100644 (file)
@@ -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.  */
index 800c5df130d95fdf92fdb9d54a8ab5bdfce91bc1..37d36538f5f6a32c3835af120de5e5d90aa1db07 100644 (file)
@@ -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)))