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 ();
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);
}
/* 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 }
{"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}}
/* 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
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
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
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.