diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 25fa5dd57cd..49ab51042c5 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -155,6 +155,7 @@ extern void rs6000_split_logical (rtx [], enum rtx_code, bool, bool, bool); extern bool rs6000_function_pcrel_p (struct function *); extern bool rs6000_pcrel_p (void); extern bool rs6000_fndecl_pcrel_p (const_tree); +extern void rs6000_output_addr_vec_elt (FILE *, int); /* Different PowerPC instruction formats that are used by GCC. There are various other instruction formats used by the PowerPC hardware, but these diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index b58eeae2b98..7e441f7e730 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1367,6 +1367,9 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA rs6000_output_addr_const_extra +#undef TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC +#define TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC rs6000_gen_pic_addr_diff_vec + #undef TARGET_LEGITIMIZE_ADDRESS #define TARGET_LEGITIMIZE_ADDRESS rs6000_legitimize_address @@ -27053,6 +27056,27 @@ rs6000_emit_xxspltidp_v2df (rtx dst, long value) emit_insn( gen_xxspltidp_v2df_inst (dst, GEN_INT (value))); } +/* Implement TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC. + Marco relative jumpstables indicates addr_diff_vec or addr_vec. */ + +static bool +rs6000_gen_pic_addr_diff_vec (void) +{ + return rs6000_relative_jumptables; +} + +void +rs6000_output_addr_vec_elt (FILE *file, int value) +{ + const char *directive = TARGET_64BIT ? DOUBLE_INT_ASM_OP : "\t.long\t"; + char buf[100]; + + fprintf (file, "%s", directive); + ASM_GENERATE_INTERNAL_LABEL (buf, "L", value); + assemble_name (file, buf); + fprintf (file, "\n"); +} + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-rs6000.h" diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index bbd8060e143..4a948e25f71 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1754,15 +1754,15 @@ typedef struct rs6000_args /* #define LEGITIMATE_PIC_OPERAND_P (X) */ -/* Specify the machine mode that this machine uses - for the index in the tablejump instruction. */ -#define CASE_VECTOR_MODE SImode - /* Define as C expression which evaluates to nonzero 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 1 +#define CASE_VECTOR_PC_RELATIVE rs6000_relative_jumptables + +/* Specify the machine mode that this machine uses + for the index in the tablejump instruction. */ +#define CASE_VECTOR_MODE (rs6000_relative_jumptables ? SImode : Pmode) /* Define this as 1 if `char' should by default be signed; else as 0. */ #define DEFAULT_SIGNED_CHAR 0 @@ -2192,6 +2192,11 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */ putc ('\n', FILE); \ } while (0) +/* This is how to output an element of a case-vector + that is non-relative. */ +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + rs6000_output_addr_vec_elt ((FILE), (VALUE)) + /* This is how to output an assembler line that says to advance the location counter to a multiple of 2**LOG bytes. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 779bfd11237..4f1265d6437 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -12697,15 +12697,27 @@ "" { if (rs6000_speculate_indirect_jumps) - emit_jump_insn (gen_tablejump_normal (Pmode, operands[0], operands[1])); + { + if (rs6000_relative_jumptables) + emit_jump_insn (gen_tablejump_normal (Pmode, operands[0], operands[1])); + else + emit_jump_insn (gen_tablejump_absolute (Pmode, operands[0], + operands[1])); + } else { rtx ccreg = gen_reg_rtx (CCmode); rtx jump; - if (TARGET_32BIT) - jump = gen_tablejumpsi_nospec (operands[0], operands[1], ccreg); + if (rs6000_relative_jumptables) + { + if (TARGET_32BIT) + jump = gen_tablejumpsi_nospec (operands[0], operands[1], ccreg); + else + jump = gen_tablejumpdi_nospec (operands[0], operands[1], ccreg); + } else - jump = gen_tablejumpdi_nospec (operands[0], operands[1], ccreg); + jump = gen_tablejump_absolute_nospec (Pmode, operands[0], operands[1], + ccreg); emit_jump_insn (jump); } DONE; @@ -12714,7 +12726,7 @@ (define_expand "@tablejump_normal" [(use (match_operand:SI 0)) (use (match_operand:P 1))] - "rs6000_speculate_indirect_jumps" + "rs6000_speculate_indirect_jumps && rs6000_relative_jumptables" { rtx off; operands[0] = force_reg (SImode, operands[0]); @@ -12735,11 +12747,23 @@ DONE; }) +(define_expand "@tablejump_absolute" + [(use (match_operand:P 0)) + (use (match_operand:P 1))] + "rs6000_speculate_indirect_jumps && !rs6000_relative_jumptables" +{ + rtx addr = gen_reg_rtx (Pmode); + emit_move_insn (addr, operands[0]); + + emit_jump_insn (gen_tablejump_insn_normal (Pmode, addr, operands[1])); + DONE; +}) + (define_expand "@tablejump_nospec" [(use (match_operand:SI 0)) (use (match_operand:P 1)) (use (match_operand:CC 2))] - "!rs6000_speculate_indirect_jumps" + "!rs6000_speculate_indirect_jumps && rs6000_relative_jumptables" { rtx off; operands[0] = force_reg (SImode, operands[0]); @@ -12761,6 +12785,20 @@ DONE; }) +(define_expand "@tablejump_absolute_nospec" + [(use (match_operand:P 0)) + (use (match_operand:P 1)) + (use (match_operand:CC 2))] + "!rs6000_speculate_indirect_jumps && !rs6000_relative_jumptables" +{ + rtx addr = gen_reg_rtx (Pmode); + emit_move_insn (addr, operands[0]); + + emit_jump_insn (gen_tablejump_insn_nospec (Pmode, addr, operands[1], + operands[2])); + DONE; +}) + (define_insn "@tablejump_insn_normal" [(set (pc) (match_operand:P 0 "register_operand" "c,*l")) diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index b2a70e88ca8..2888172cb27 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -589,3 +589,6 @@ Generate (do not generate) pc-relative memory addressing. mmma Target Report Mask(MMA) Var(rs6000_isa_flags) Generate (do not generate) MMA instructions. + +mrelative-jumptables +Target Undocumented Var(rs6000_relative_jumptables) Init(1) Save