aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorJeff Law <law@gcc.gnu.org>1997-07-25 11:02:37 -0600
committerJeff Law <law@gcc.gnu.org>1997-07-25 11:02:37 -0600
commit3e056efc31aab68f650a3fa5918ca2d7fb516852 (patch)
tree6efe17b5c1f3712932f0777e4cc93730a0356e51 /gcc/config
parentb60334e840e077c460eb5e9a08f990c9844f2a48 (diff)
downloadgcc-3e056efc31aab68f650a3fa5918ca2d7fb516852.zip
gcc-3e056efc31aab68f650a3fa5918ca2d7fb516852.tar.gz
gcc-3e056efc31aab68f650a3fa5918ca2d7fb516852.tar.bz2
pa.c (pa_reorg): If TARGET_BIG_SWITCH, then do not explode ADDR_VEC insns.
* pa.c (pa_reorg): If TARGET_BIG_SWITCH, then do not explode ADDR_VEC insns. Slightly rework code which explodes ADDR_VEC insns. * pa.h (TARGET_BIG_SWITCH): Define. (TARGET_SWITCHES): Add "big-switch" and "no-big-switch". (CASE_VECTOR_MODE): Use TI or DI depending on TARGET_BIG_SWITCH. (CASE_DROPS_THROUGH): Remove definition. (ASM_OUTPUT_ADDR_VEC_ELT): Rewrite to handle TARGET_BIG_SWITCH. (ASM_OUTPUT_ADDR_DIFF_ELT): Likewise. * pa.md (casesi): Rework to avoid some potential long branch problems (also makes generated code faster!). Handle TARGET_BIG_SWITCH. (casesi0): Corresponding changes. From-SVN: r14528
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/pa/pa.c25
-rw-r--r--gcc/config/pa/pa.h24
-rw-r--r--gcc/config/pa/pa.md38
3 files changed, 45 insertions, 42 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 5297cad..db6c495 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -5807,7 +5807,7 @@ pa_reorg (insns)
pa_combine_instructions (get_insns ());
/* This is fairly cheap, so always run it if optimizing. */
- if (optimize > 0)
+ if (optimize > 0 && !TARGET_BIG_SWITCH)
{
/* Find and explode all ADDR_VEC insns. */
insns = get_insns ();
@@ -5831,28 +5831,33 @@ pa_reorg (insns)
for (i = 0; i < length; i++)
{
+ /* Emit a label before each jump to keep jump.c from
+ removing this code. */
+ tmp = gen_label_rtx ();
+ LABEL_NUSES (tmp) = 1;
+ emit_label_after (tmp, location);
+ location = NEXT_INSN (location);
+
/* Emit the jump itself. */
tmp = gen_switch_jump (XEXP (XVECEXP (pattern, 0, i), 0));
tmp = emit_jump_insn_after (tmp, location);
JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 0, i), 0);
LABEL_NUSES (JUMP_LABEL (tmp))++;
+ location = NEXT_INSN (location);
/* Emit a BARRIER after the jump. */
- location = NEXT_INSN (location);
emit_barrier_after (location);
-
- /* Put a CODE_LABEL before each so jump.c does not optimize
- the jumps away. */
- location = NEXT_INSN (location);
- tmp = gen_label_rtx ();
- LABEL_NUSES (tmp) = 1;
- emit_label_after (tmp, location);
location = NEXT_INSN (location);
}
/* If needed, emit marker for the end of the branch table. */
if (TARGET_GAS)
- emit_insn_before (gen_end_brtab (), location);
+ {
+ emit_insn_before (gen_end_brtab (), location);
+ location = NEXT_INSN (location);
+ emit_barrier_after (location);
+ }
+
/* Delete the ADDR_VEC. */
delete_insn (insn);
}
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 7855904..daf63c7 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -112,6 +112,10 @@ extern int target_flags;
/* Use a faster sequence for indirect calls. */
#define TARGET_FAST_INDIRECT_CALLS (target_flags & 1024)
+/* Generate code with big switch statements to avoid out of range branches
+ occuring within the switch table. */
+#define TARGET_BIG_SWITCH (target_flags & 2048)
+
/* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces,
each pair being { "NAME", VALUE }
@@ -143,6 +147,8 @@ extern int target_flags;
{"no-long-load-store", -512},\
{"fast-indirect-calls", 1024},\
{"no-fast-indirect-calls", -1024},\
+ {"big-switch", 2048}, \
+ {"no-big-switch", -2048}, \
{"linker-opt", 0}, \
{ "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}}
@@ -1677,14 +1683,8 @@ while (0)
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
-#define CASE_VECTOR_MODE DImode
-
-/* Define this if the tablejump instruction expects the table
- to contain offsets from the address of the table.
- Do not define this if the table should contain absolute addresses. */
-/* #define CASE_VECTOR_PC_RELATIVE */
+#define CASE_VECTOR_MODE (TARGET_BIG_SWITCH ? TImode : DImode)
-#define CASE_DROPS_THROUGH
/* Specify the tree operation to be used to convert reals to integers. */
#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
@@ -2205,7 +2205,10 @@ DTORS_SECTION_FUNCTION
impossible. */
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
- fprintf (FILE, "\tb L$%04d\n\tnop\n", 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
@@ -2218,7 +2221,10 @@ DTORS_SECTION_FUNCTION
rather than a table of absolute addresses. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
- fprintf (FILE, "\tb L$%04d\n\tnop\n", VALUE)
+ if (TARGET_BIG_SWITCH) \
+ fprintf (FILE, "\tstw %%r1,-16(%%r30)\n\tldw T'L$%04d(%%r19),%%r1\n\tbv 0(%%r1)\n\tldw -16(%%r30),%%r1\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
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index 3551974..848567a 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -4006,37 +4006,29 @@
operands[0] = reg;
}
- if (!INT_11_BITS (operands[2]))
+ if (!INT_5_BITS (operands[2]))
operands[2] = force_reg (SImode, operands[2]);
- emit_jump_insn (gen_casesi0 (operands[0], operands[2],
- operands[3], operands[4]));
+ emit_insn (gen_cmpsi (operands[0], operands[2]));
+ emit_jump_insn (gen_bgtu (operands[4]));
+ if (TARGET_BIG_SWITCH)
+ {
+ rtx temp = gen_reg_rtx (SImode);
+ emit_move_insn (temp, gen_rtx (PLUS, SImode, operands[0], operands[0]));
+ operands[0] = temp;
+ }
+ emit_jump_insn (gen_casesi0 (operands[0], operands[3]));
DONE;
}")
(define_insn "casesi0"
- [(set (pc)
- (if_then_else (leu (match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "arith11_operand" "rI"))
- (plus:SI (mem:SI (plus:SI (pc) (match_dup 0)))
- (label_ref (match_operand 2 "" "")))
- (pc)))
- (use (label_ref (match_operand 3 "" "")))]
+ [(set (pc) (plus:SI
+ (mem:SI (plus:SI (pc) (match_operand 0 "register_operand" "r")))
+ (label_ref (match_operand 1 "" ""))))]
""
- "*
-{
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- operands[1] = GEN_INT (~INTVAL (operands[1]));
- return \"addi,uv %1,%0,0\;blr,n %0,0\;b,n %l3\";
- }
- else
- {
- return \"sub,>> %0,%1,0\;blr,n %0,0\;b,n %l3\";
- }
-}"
+ "blr %0,0\;nop"
[(set_attr "type" "multi")
- (set_attr "length" "12")])
+ (set_attr "length" "8")])
;; Need nops for the calls because execution is supposed to continue
;; past; we don't want to nullify an instruction that we need.