invoke.texi: Add mcmodel to powerpc options.
* doc/invoke.texi: Add mcmodel to powerpc options. * configure.ac: Add HAVE_LD_LARGE_TOC test. * configure: Regenerate. * config.in: Regenerate. * config/rs6000/linux64.opt (mcmodel): New. * config/rs6000/linux64.h (TARGET_USES_LINUX64_OPT): Define. (TARGET_CMODEL): Define. (SUBSUBTARGET_OVERRIDE_OPTIONS): Check user -mcmodel choice, select CMODEL_MEDIUM default. * config/rs6000/rs6000.h (enum rs6000_cmodel): New. (TARGET_CMODEL): Define default. * config/rs6000/rs6000.c (cmodel): New variable. (rs6000_explicit_options): Add cmodel field. (rs6000_handle_option): Handle -mcmodel. (create_TOC_reference): Add largetoc_reg param. Generate high, lo_sum rtl for CMODEL_MEDIUM and CMODEL_LARGE. Update all callers. (rs6000_delegitimize_address): Recognise new toc reference rtl and minimal-toc rtl. (rs6000_legitimize_reload_address): Handle new toc references. (print_operand_address): Handle legitimate_constant_pool_address_p match before lo_sum. (rs6000_eliminate_indexed_memrefs): Tidy. (rs6000_emit_move): Tweak threshold for inlining constants. Keep rs6000_emit_allocate_stack large stack frame offsets loaded into r0 inline. (rs6000_generate_compare <cmptf_internal2>): One more clobber. (tocrel_base, tocrel_offset): New variables. (toc_relative_expr_p): Set them here. (print_operand_address): Skip over any offset on constant pool address. (rs6000_output_addr_const_extra): Print tocrel_offset before @toc. (rs6000_mode_dependent_address <LO_SUM>): False for new toc refs. (offsettable_ok_by_alignment): New function. (rs6000_emit_move): Address suitably aligned local symbol_refs relative to the toc pointer for -mcmodel=medium. (legitimate_constant_pool_address_p): Make param const_rtx. Add strict param. Allow lo_sum version of addressing. Verify reg used for -mminimal-toc and -mcmodel != small. Update all callers. * config/rs6000/constraints.md: Update for above change. * config/rs6000/predicates.md: Likewise. * config/rs6000/rs6000.md (tls_gd_aix): Generate -mcmodel=medium/large code. (tls_gd): Split for -mcmodel=medium/large. (tls_gd_high, tls_gd_low): New. (tls_ld_aix, tls_ld, tls_ld_high, tls_ld_low): Similarly. (tls_got_dtprel, tls_got_dtprel_high, tls_got_dtprel_low): Similarly. (tls_got_tprel, tls_got_tprel_high, tls_got_tprel_low): Similarly. (largetoc_high, largetoc_low): New. (cmptf_internal2): Add clobber. * config/rs6000/rs6000-protos.h: Update. From-SVN: r160773
This commit is contained in:
parent
309b8e7dd6
commit
070b27da92
@ -1,3 +1,56 @@
|
||||
2010-06-15 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* doc/invoke.texi: Add mcmodel to powerpc options.
|
||||
* configure.ac: Add HAVE_LD_LARGE_TOC test.
|
||||
* configure: Regenerate.
|
||||
* config.in: Regenerate.
|
||||
* config/rs6000/linux64.opt (mcmodel): New.
|
||||
* config/rs6000/linux64.h (TARGET_USES_LINUX64_OPT): Define.
|
||||
(TARGET_CMODEL): Define.
|
||||
(SUBSUBTARGET_OVERRIDE_OPTIONS): Check user -mcmodel choice,
|
||||
select CMODEL_MEDIUM default.
|
||||
* config/rs6000/rs6000.h (enum rs6000_cmodel): New.
|
||||
(TARGET_CMODEL): Define default.
|
||||
* config/rs6000/rs6000.c (cmodel): New variable.
|
||||
(rs6000_explicit_options): Add cmodel field.
|
||||
(rs6000_handle_option): Handle -mcmodel.
|
||||
(create_TOC_reference): Add largetoc_reg param. Generate high,
|
||||
lo_sum rtl for CMODEL_MEDIUM and CMODEL_LARGE. Update all callers.
|
||||
(rs6000_delegitimize_address): Recognise new toc reference rtl
|
||||
and minimal-toc rtl.
|
||||
(rs6000_legitimize_reload_address): Handle new toc references.
|
||||
(print_operand_address): Handle legitimate_constant_pool_address_p
|
||||
match before lo_sum.
|
||||
(rs6000_eliminate_indexed_memrefs): Tidy.
|
||||
(rs6000_emit_move): Tweak threshold for inlining constants.
|
||||
Keep rs6000_emit_allocate_stack large stack frame offsets
|
||||
loaded into r0 inline.
|
||||
(rs6000_generate_compare <cmptf_internal2>): One more clobber.
|
||||
(tocrel_base, tocrel_offset): New variables.
|
||||
(toc_relative_expr_p): Set them here.
|
||||
(print_operand_address): Skip over any offset on constant pool
|
||||
address.
|
||||
(rs6000_output_addr_const_extra): Print tocrel_offset before @toc.
|
||||
(rs6000_mode_dependent_address <LO_SUM>): False for new toc refs.
|
||||
(offsettable_ok_by_alignment): New function.
|
||||
(rs6000_emit_move): Address suitably aligned local symbol_refs
|
||||
relative to the toc pointer for -mcmodel=medium.
|
||||
(legitimate_constant_pool_address_p): Make param const_rtx. Add
|
||||
strict param. Allow lo_sum version of addressing. Verify reg
|
||||
used for -mminimal-toc and -mcmodel != small. Update all callers.
|
||||
* config/rs6000/constraints.md: Update for above change.
|
||||
* config/rs6000/predicates.md: Likewise.
|
||||
* config/rs6000/rs6000.md (tls_gd_aix): Generate -mcmodel=medium/large
|
||||
code.
|
||||
(tls_gd): Split for -mcmodel=medium/large.
|
||||
(tls_gd_high, tls_gd_low): New.
|
||||
(tls_ld_aix, tls_ld, tls_ld_high, tls_ld_low): Similarly.
|
||||
(tls_got_dtprel, tls_got_dtprel_high, tls_got_dtprel_low): Similarly.
|
||||
(tls_got_tprel, tls_got_tprel_high, tls_got_tprel_low): Similarly.
|
||||
(largetoc_high, largetoc_low): New.
|
||||
(cmptf_internal2): Add clobber.
|
||||
* config/rs6000/rs6000-protos.h: Update.
|
||||
|
||||
2010-06-14 Changpeng Fang <changpeng.fang@amd.com>
|
||||
|
||||
* tree-ssa-loop-prefetch.c (nothing_to_prefetch_p): New. Return
|
||||
|
@ -1168,6 +1168,12 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Define if your PowerPC64 linker supports a large TOC. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_LD_LARGE_TOC
|
||||
#endif
|
||||
|
||||
|
||||
/* Define if your PowerPC64 linker only needs function descriptor syms. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_LD_NO_DOT_SYMS
|
||||
|
@ -166,7 +166,7 @@ usually better to use @samp{m} or @samp{es} in @code{asm} statements)"
|
||||
|
||||
(define_constraint "R"
|
||||
"AIX TOC entry"
|
||||
(match_test "legitimate_constant_pool_address_p (op)"))
|
||||
(match_test "legitimate_constant_pool_address_p (op, false)"))
|
||||
|
||||
;; General constraints
|
||||
|
||||
|
@ -63,6 +63,16 @@ extern int dot_symbols;
|
||||
|
||||
#define TARGET_PROFILE_KERNEL profile_kernel
|
||||
|
||||
#define TARGET_USES_LINUX64_OPT 1
|
||||
#ifdef HAVE_LD_LARGE_TOC
|
||||
extern enum rs6000_cmodel cmodel;
|
||||
#undef TARGET_CMODEL
|
||||
#define TARGET_CMODEL cmodel
|
||||
#define SET_CMODEL(opt) cmodel = opt
|
||||
#else
|
||||
#define SET_CMODEL(opt)
|
||||
#endif
|
||||
|
||||
#undef PROCESSOR_DEFAULT
|
||||
#define PROCESSOR_DEFAULT PROCESSOR_POWER6
|
||||
#undef PROCESSOR_DEFAULT64
|
||||
@ -114,6 +124,23 @@ extern int dot_symbols;
|
||||
target_flags |= MASK_POWERPC64; \
|
||||
error ("-m64 requires a PowerPC64 cpu"); \
|
||||
} \
|
||||
if ((target_flags_explicit & MASK_MINIMAL_TOC) != 0) \
|
||||
{ \
|
||||
if (rs6000_explicit_options.cmodel \
|
||||
&& cmodel != CMODEL_SMALL) \
|
||||
error ("-mcmodel incompatible with other toc options"); \
|
||||
SET_CMODEL (CMODEL_SMALL); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (!rs6000_explicit_options.cmodel) \
|
||||
SET_CMODEL (CMODEL_MEDIUM); \
|
||||
if (cmodel != CMODEL_SMALL) \
|
||||
{ \
|
||||
TARGET_NO_FP_IN_TOC = 0; \
|
||||
TARGET_NO_SUM_IN_TOC = 0; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
@ -124,6 +151,11 @@ extern int dot_symbols;
|
||||
TARGET_PROFILE_KERNEL = 0; \
|
||||
error (INVALID_32BIT, "profile-kernel"); \
|
||||
} \
|
||||
if (rs6000_explicit_options.cmodel) \
|
||||
{ \
|
||||
SET_CMODEL (CMODEL_SMALL); \
|
||||
error (INVALID_32BIT, "cmodel"); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
@ -22,3 +22,7 @@
|
||||
mprofile-kernel
|
||||
Target Report Var(profile_kernel)
|
||||
Call mcount for profiling before a function prologue
|
||||
|
||||
mcmodel=
|
||||
Target RejectNegative Joined
|
||||
Select code model
|
||||
|
@ -837,7 +837,7 @@
|
||||
return 1;
|
||||
|
||||
/* A SYMBOL_REF referring to the TOC is valid. */
|
||||
if (legitimate_constant_pool_address_p (op))
|
||||
if (legitimate_constant_pool_address_p (op, false))
|
||||
return 1;
|
||||
|
||||
/* A constant pool expression (relative to the TOC) is valid */
|
||||
|
@ -39,7 +39,7 @@ extern int small_data_operand (rtx, enum machine_mode);
|
||||
extern bool toc_relative_expr_p (rtx);
|
||||
extern bool invalid_e500_subreg (rtx, enum machine_mode);
|
||||
extern void validate_condition_mode (enum rtx_code, enum machine_mode);
|
||||
extern bool legitimate_constant_pool_address_p (rtx);
|
||||
extern bool legitimate_constant_pool_address_p (const_rtx, bool);
|
||||
extern bool legitimate_indirect_address_p (rtx, int);
|
||||
extern bool legitimate_indexed_address_p (rtx, int);
|
||||
extern bool avoiding_indexed_address_p (enum machine_mode);
|
||||
@ -111,7 +111,7 @@ extern void rs6000_emit_swrsqrt (rtx, rtx);
|
||||
extern void output_toc (FILE *, rtx, int, enum machine_mode);
|
||||
extern rtx rs6000_longcall_ref (rtx);
|
||||
extern void rs6000_fatal_bad_address (rtx);
|
||||
extern rtx create_TOC_reference (rtx);
|
||||
extern rtx create_TOC_reference (rtx, rtx);
|
||||
extern void rs6000_split_multireg_move (rtx, rtx);
|
||||
extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
|
||||
extern rtx rs6000_secondary_memory_needed_rtx (enum machine_mode);
|
||||
|
@ -279,6 +279,9 @@ static GTY(()) section *toc_section;
|
||||
/* String from -malign-XXXXX. */
|
||||
int rs6000_alignment_flags;
|
||||
|
||||
/* Code model for 64-bit linux. */
|
||||
enum rs6000_cmodel cmodel;
|
||||
|
||||
/* True for any options that were explicitly set. */
|
||||
static struct {
|
||||
bool aix_struct_ret; /* True if -maix-struct-ret was used. */
|
||||
@ -290,6 +293,7 @@ static struct {
|
||||
bool long_double; /* True if -mlong-double- was used. */
|
||||
bool ieee; /* True if -mabi=ieee/ibmlongdouble used. */
|
||||
bool vrsave; /* True if -mvrsave was used. */
|
||||
bool cmodel; /* True if -mcmodel was used. */
|
||||
} rs6000_explicit_options;
|
||||
|
||||
struct builtin_description
|
||||
@ -3645,6 +3649,22 @@ rs6000_handle_option (size_t code, const char *arg, int value)
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LD_LARGE_TOC) && defined (TARGET_USES_LINUX64_OPT)
|
||||
case OPT_mcmodel_:
|
||||
if (strcmp (arg, "small") == 0)
|
||||
cmodel = CMODEL_SMALL;
|
||||
else if (strcmp (arg, "medium") == 0)
|
||||
cmodel = CMODEL_MEDIUM;
|
||||
else if (strcmp (arg, "large") == 0)
|
||||
cmodel = CMODEL_LARGE;
|
||||
else
|
||||
{
|
||||
error ("invalid option for -mcmodel: '%s'", arg);
|
||||
return false;
|
||||
}
|
||||
rs6000_explicit_options.cmodel = true;
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_USES_AIX64_OPT
|
||||
case OPT_maix64:
|
||||
#else
|
||||
@ -5098,26 +5118,29 @@ constant_pool_expr_p (rtx op)
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (base), Pmode));
|
||||
}
|
||||
|
||||
static rtx tocrel_base, tocrel_offset;
|
||||
|
||||
bool
|
||||
toc_relative_expr_p (rtx op)
|
||||
{
|
||||
rtx base, offset;
|
||||
|
||||
if (GET_CODE (op) != CONST)
|
||||
return false;
|
||||
|
||||
split_const (op, &base, &offset);
|
||||
return (GET_CODE (base) == UNSPEC
|
||||
&& XINT (base, 1) == UNSPEC_TOCREL);
|
||||
split_const (op, &tocrel_base, &tocrel_offset);
|
||||
return (GET_CODE (tocrel_base) == UNSPEC
|
||||
&& XINT (tocrel_base, 1) == UNSPEC_TOCREL);
|
||||
}
|
||||
|
||||
bool
|
||||
legitimate_constant_pool_address_p (rtx x)
|
||||
legitimate_constant_pool_address_p (const_rtx x, bool strict)
|
||||
{
|
||||
return (TARGET_TOC
|
||||
&& GET_CODE (x) == PLUS
|
||||
&& (GET_CODE (x) == PLUS || GET_CODE (x) == LO_SUM)
|
||||
&& GET_CODE (XEXP (x, 0)) == REG
|
||||
&& (TARGET_MINIMAL_TOC || REGNO (XEXP (x, 0)) == TOC_REGISTER)
|
||||
&& (REGNO (XEXP (x, 0)) == TOC_REGISTER
|
||||
|| ((TARGET_MINIMAL_TOC
|
||||
|| TARGET_CMODEL != CMODEL_SMALL)
|
||||
&& INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict)))
|
||||
&& toc_relative_expr_p (XEXP (x, 1)));
|
||||
}
|
||||
|
||||
@ -5146,7 +5169,7 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
|
||||
return false;
|
||||
if (!reg_offset_addressing_ok_p (mode))
|
||||
return virtual_stack_registers_memory_p (x);
|
||||
if (legitimate_constant_pool_address_p (x))
|
||||
if (legitimate_constant_pool_address_p (x, strict))
|
||||
return true;
|
||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
|
||||
return false;
|
||||
@ -5494,7 +5517,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
|
||||
&& constant_pool_expr_p (x)
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
|
||||
{
|
||||
return create_TOC_reference (x);
|
||||
rtx reg = TARGET_CMODEL != CMODEL_SMALL ? gen_reg_rtx (Pmode) : NULL_RTX;
|
||||
return create_TOC_reference (x, reg);
|
||||
}
|
||||
else
|
||||
return x;
|
||||
@ -5585,10 +5609,13 @@ rs6000_delegitimize_address (rtx orig_x)
|
||||
if (MEM_P (x))
|
||||
x = XEXP (x, 0);
|
||||
|
||||
if (GET_CODE (x) == PLUS
|
||||
&& GET_CODE (XEXP (x, 1)) == CONST
|
||||
if ((GET_CODE (x) == PLUS
|
||||
|| GET_CODE (x) == LO_SUM)
|
||||
&& GET_CODE (XEXP (x, 0)) == REG
|
||||
&& REGNO (XEXP (x, 0)) == TOC_REGISTER)
|
||||
&& (REGNO (XEXP (x, 0)) == TOC_REGISTER
|
||||
|| TARGET_MINIMAL_TOC
|
||||
|| TARGET_CMODEL != CMODEL_SMALL)
|
||||
&& GET_CODE (XEXP (x, 1)) == CONST)
|
||||
{
|
||||
y = XEXP (XEXP (x, 1), 0);
|
||||
if (GET_CODE (y) == UNSPEC
|
||||
@ -5600,7 +5627,6 @@ rs6000_delegitimize_address (rtx orig_x)
|
||||
else
|
||||
return replace_equiv_address_nv (orig_x, y);
|
||||
}
|
||||
return orig_x;
|
||||
}
|
||||
|
||||
if (TARGET_MACHO
|
||||
@ -5896,6 +5922,24 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (TARGET_CMODEL != CMODEL_SMALL
|
||||
&& GET_CODE (x) == LO_SUM
|
||||
&& GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
|
||||
&& REGNO (XEXP (XEXP (x, 0), 0)) == TOC_REGISTER
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH
|
||||
&& GET_CODE (XEXP (x, 1)) == CONST
|
||||
&& GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC
|
||||
&& XINT (XEXP (XEXP (x, 1), 0), 1) == UNSPEC_TOCREL
|
||||
&& rtx_equal_p (XEXP (XEXP (XEXP (x, 0), 1), 0), XEXP (x, 1)))
|
||||
{
|
||||
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
|
||||
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
|
||||
opnum, (enum reload_type) type);
|
||||
*win = 1;
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Force ld/std non-word aligned offset into base register by wrapping
|
||||
in offset 0. */
|
||||
if (GET_CODE (x) == PLUS
|
||||
@ -6021,7 +6065,11 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
|
||||
&& constant_pool_expr_p (x)
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
|
||||
{
|
||||
x = create_TOC_reference (x);
|
||||
x = create_TOC_reference (x, NULL_RTX);
|
||||
if (TARGET_CMODEL != CMODEL_SMALL)
|
||||
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
|
||||
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
|
||||
opnum, (enum reload_type) type);
|
||||
*win = 1;
|
||||
return x;
|
||||
}
|
||||
@ -6104,7 +6152,7 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
|
||||
return 1;
|
||||
if (reg_offset_p && legitimate_small_data_p (mode, x))
|
||||
return 1;
|
||||
if (reg_offset_p && legitimate_constant_pool_address_p (x))
|
||||
if (reg_offset_p && legitimate_constant_pool_address_p (x, reg_ok_strict))
|
||||
return 1;
|
||||
/* If not REG_OK_STRICT (before reload) let pass any stack offset. */
|
||||
if (! reg_ok_strict
|
||||
@ -6212,7 +6260,9 @@ rs6000_mode_dependent_address (const_rtx addr)
|
||||
break;
|
||||
|
||||
case LO_SUM:
|
||||
return true;
|
||||
/* Anything in the constant pool is sufficiently aligned that
|
||||
all bytes have the same high part address. */
|
||||
return !legitimate_constant_pool_address_p (addr, false);
|
||||
|
||||
/* Auto-increment cases are now treated generically in recog.c. */
|
||||
case PRE_MODIFY:
|
||||
@ -6568,23 +6618,54 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
|
||||
static void
|
||||
rs6000_eliminate_indexed_memrefs (rtx operands[2])
|
||||
{
|
||||
if (reload_in_progress)
|
||||
return;
|
||||
|
||||
if (GET_CODE (operands[0]) == MEM
|
||||
&& GET_CODE (XEXP (operands[0], 0)) != REG
|
||||
&& ! legitimate_constant_pool_address_p (XEXP (operands[0], 0))
|
||||
&& ! reload_in_progress)
|
||||
&& ! legitimate_constant_pool_address_p (XEXP (operands[0], 0), false))
|
||||
operands[0]
|
||||
= replace_equiv_address (operands[0],
|
||||
copy_addr_to_reg (XEXP (operands[0], 0)));
|
||||
|
||||
if (GET_CODE (operands[1]) == MEM
|
||||
&& GET_CODE (XEXP (operands[1], 0)) != REG
|
||||
&& ! legitimate_constant_pool_address_p (XEXP (operands[1], 0))
|
||||
&& ! reload_in_progress)
|
||||
&& ! legitimate_constant_pool_address_p (XEXP (operands[1], 0), false))
|
||||
operands[1]
|
||||
= replace_equiv_address (operands[1],
|
||||
copy_addr_to_reg (XEXP (operands[1], 0)));
|
||||
}
|
||||
|
||||
/* Return true if memory accesses to DECL are known to never straddle
|
||||
a 32k boundary. */
|
||||
|
||||
static bool
|
||||
offsettable_ok_by_alignment (tree decl)
|
||||
{
|
||||
unsigned HOST_WIDE_INT dsize;
|
||||
|
||||
/* Presume any compiler generated symbol_ref is suitably aligned. */
|
||||
if (!decl)
|
||||
return true;
|
||||
|
||||
if (TREE_CODE (decl) != VAR_DECL
|
||||
&& TREE_CODE (decl) != PARM_DECL
|
||||
&& TREE_CODE (decl) != RESULT_DECL
|
||||
&& TREE_CODE (decl) != FIELD_DECL)
|
||||
return true;
|
||||
|
||||
if (!host_integerp (DECL_SIZE_UNIT (decl), 1))
|
||||
return false;
|
||||
|
||||
dsize = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
|
||||
if (dsize <= 1)
|
||||
return true;
|
||||
if (dsize > 32768)
|
||||
return false;
|
||||
|
||||
return DECL_ALIGN_UNIT (decl) >= dsize;
|
||||
}
|
||||
|
||||
/* Emit a move from SOURCE to DEST in mode MODE. */
|
||||
void
|
||||
rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
|
||||
@ -6898,25 +6979,43 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
|
||||
/* If this is a SYMBOL_REF that refers to a constant pool entry,
|
||||
and we have put it in the TOC, we just need to make a TOC-relative
|
||||
reference to it. */
|
||||
if (TARGET_TOC
|
||||
&& GET_CODE (operands[1]) == SYMBOL_REF
|
||||
&& constant_pool_expr_p (operands[1])
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (operands[1]),
|
||||
get_pool_mode (operands[1])))
|
||||
if ((TARGET_TOC
|
||||
&& GET_CODE (operands[1]) == SYMBOL_REF
|
||||
&& constant_pool_expr_p (operands[1])
|
||||
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (operands[1]),
|
||||
get_pool_mode (operands[1])))
|
||||
|| (TARGET_CMODEL == CMODEL_MEDIUM
|
||||
&& GET_CODE (operands[1]) == SYMBOL_REF
|
||||
&& !CONSTANT_POOL_ADDRESS_P (operands[1])
|
||||
&& SYMBOL_REF_LOCAL_P (operands[1])
|
||||
&& offsettable_ok_by_alignment (SYMBOL_REF_DECL (operands[1]))))
|
||||
{
|
||||
operands[1] = create_TOC_reference (operands[1]);
|
||||
rtx reg = NULL_RTX;
|
||||
if (TARGET_CMODEL != CMODEL_SMALL)
|
||||
{
|
||||
if (can_create_pseudo_p ())
|
||||
reg = gen_reg_rtx (Pmode);
|
||||
else
|
||||
reg = operands[0];
|
||||
}
|
||||
operands[1] = create_TOC_reference (operands[1], reg);
|
||||
}
|
||||
else if (mode == Pmode
|
||||
&& CONSTANT_P (operands[1])
|
||||
&& ((GET_CODE (operands[1]) != CONST_INT
|
||||
&& ! easy_fp_constant (operands[1], mode))
|
||||
|| (GET_CODE (operands[1]) == CONST_INT
|
||||
&& num_insns_constant (operands[1], mode) > 2)
|
||||
&& (num_insns_constant (operands[1], mode)
|
||||
> (TARGET_CMODEL != CMODEL_SMALL ? 3 : 2)))
|
||||
|| (GET_CODE (operands[0]) == REG
|
||||
&& FP_REGNO_P (REGNO (operands[0]))))
|
||||
&& GET_CODE (operands[1]) != HIGH
|
||||
&& ! legitimate_constant_pool_address_p (operands[1])
|
||||
&& ! toc_relative_expr_p (operands[1]))
|
||||
&& ! legitimate_constant_pool_address_p (operands[1], false)
|
||||
&& ! toc_relative_expr_p (operands[1])
|
||||
&& (TARGET_CMODEL == CMODEL_SMALL
|
||||
|| can_create_pseudo_p ()
|
||||
|| (REG_P (operands[0])
|
||||
&& INT_REG_OK_FOR_BASE_P (operands[0], true))))
|
||||
{
|
||||
|
||||
#if TARGET_MACHO
|
||||
@ -6962,9 +7061,17 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
|
||||
get_pool_constant (XEXP (operands[1], 0)),
|
||||
get_pool_mode (XEXP (operands[1], 0))))
|
||||
{
|
||||
operands[1]
|
||||
= gen_const_mem (mode,
|
||||
create_TOC_reference (XEXP (operands[1], 0)));
|
||||
rtx tocref;
|
||||
rtx reg = NULL_RTX;
|
||||
if (TARGET_CMODEL != CMODEL_SMALL)
|
||||
{
|
||||
if (can_create_pseudo_p ())
|
||||
reg = gen_reg_rtx (Pmode);
|
||||
else
|
||||
reg = operands[0];
|
||||
}
|
||||
tocref = create_TOC_reference (XEXP (operands[1], 0), reg);
|
||||
operands[1] = gen_const_mem (mode, tocref);
|
||||
set_mem_alias_set (operands[1], get_TOC_alias_set ());
|
||||
}
|
||||
}
|
||||
@ -15328,14 +15435,6 @@ print_operand_address (FILE *file, rtx x)
|
||||
else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%s)",
|
||||
INTVAL (XEXP (x, 1)), reg_names[ REGNO (XEXP (x, 0)) ]);
|
||||
#if TARGET_ELF
|
||||
else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
|
||||
&& CONSTANT_P (XEXP (x, 1)))
|
||||
{
|
||||
output_addr_const (file, XEXP (x, 1));
|
||||
fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
|
||||
}
|
||||
#endif
|
||||
#if TARGET_MACHO
|
||||
else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
|
||||
&& CONSTANT_P (XEXP (x, 1)))
|
||||
@ -15345,11 +15444,29 @@ print_operand_address (FILE *file, rtx x)
|
||||
fprintf (file, ")(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
|
||||
}
|
||||
#endif
|
||||
else if (legitimate_constant_pool_address_p (x))
|
||||
else if (legitimate_constant_pool_address_p (x, true))
|
||||
{
|
||||
/* This hack along with a corresponding hack in
|
||||
rs6000_output_addr_const_extra arranges to output addends
|
||||
where the assembler expects to find them. eg.
|
||||
(lo_sum (reg 9)
|
||||
. (const (plus (unspec [symbol_ref ("x") tocrel]) 8)))
|
||||
without this hack would be output as "x@toc+8@l(9)". We
|
||||
want "x+8@toc@l(9)". */
|
||||
output_addr_const (file, tocrel_base);
|
||||
if (GET_CODE (x) == LO_SUM)
|
||||
fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
|
||||
else
|
||||
fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]);
|
||||
}
|
||||
#if TARGET_ELF
|
||||
else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
|
||||
&& CONSTANT_P (XEXP (x, 1)))
|
||||
{
|
||||
output_addr_const (file, XEXP (x, 1));
|
||||
fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]);
|
||||
fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
gcc_unreachable ();
|
||||
}
|
||||
@ -15363,9 +15480,14 @@ rs6000_output_addr_const_extra (FILE *file, rtx x)
|
||||
switch (XINT (x, 1))
|
||||
{
|
||||
case UNSPEC_TOCREL:
|
||||
x = XVECEXP (x, 0, 0);
|
||||
gcc_assert (GET_CODE (x) == SYMBOL_REF);
|
||||
output_addr_const (file, x);
|
||||
gcc_assert (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF);
|
||||
output_addr_const (file, XVECEXP (x, 0, 0));
|
||||
if (x == tocrel_base && tocrel_offset != const0_rtx)
|
||||
{
|
||||
if (INTVAL (tocrel_offset) >= 0)
|
||||
fprintf (file, "+");
|
||||
output_addr_const (file, tocrel_offset);
|
||||
}
|
||||
if (!TARGET_AIX || (TARGET_ELF && TARGET_MINIMAL_TOC))
|
||||
{
|
||||
putc ('-', file);
|
||||
@ -15689,7 +15811,7 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
|
||||
&& !TARGET_IEEEQUAD
|
||||
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128)
|
||||
emit_insn (gen_rtx_PARALLEL (VOIDmode,
|
||||
gen_rtvec (9,
|
||||
gen_rtvec (10,
|
||||
gen_rtx_SET (VOIDmode,
|
||||
compare_result,
|
||||
gen_rtx_COMPARE (comp_mode, op0, op1)),
|
||||
@ -15700,7 +15822,8 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode)
|
||||
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
|
||||
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
|
||||
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
|
||||
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)))));
|
||||
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
|
||||
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (Pmode)))));
|
||||
else if (GET_CODE (op1) == UNSPEC
|
||||
&& XINT (op1, 1) == UNSPEC_SP_TEST)
|
||||
{
|
||||
@ -18259,8 +18382,10 @@ uses_TOC (void)
|
||||
#endif
|
||||
|
||||
rtx
|
||||
create_TOC_reference (rtx symbol)
|
||||
create_TOC_reference (rtx symbol, rtx largetoc_reg)
|
||||
{
|
||||
rtx tocrel, tocreg;
|
||||
|
||||
if (TARGET_DEBUG_ADDR)
|
||||
{
|
||||
if (GET_CODE (symbol) == SYMBOL_REF)
|
||||
@ -18276,10 +18401,23 @@ create_TOC_reference (rtx symbol)
|
||||
|
||||
if (!can_create_pseudo_p ())
|
||||
df_set_regs_ever_live (TOC_REGISTER, true);
|
||||
return gen_rtx_PLUS (Pmode,
|
||||
gen_rtx_REG (Pmode, TOC_REGISTER),
|
||||
gen_rtx_CONST (Pmode,
|
||||
gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_TOCREL)));
|
||||
|
||||
tocrel = gen_rtx_CONST (Pmode,
|
||||
gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol),
|
||||
UNSPEC_TOCREL));
|
||||
tocreg = gen_rtx_REG (Pmode, TOC_REGISTER);
|
||||
if (TARGET_CMODEL != CMODEL_SMALL)
|
||||
{
|
||||
rtx hi = gen_rtx_PLUS (Pmode, tocreg, gen_rtx_HIGH (Pmode, tocrel));
|
||||
if (largetoc_reg != NULL)
|
||||
{
|
||||
emit_move_insn (largetoc_reg, hi);
|
||||
hi = largetoc_reg;
|
||||
}
|
||||
return gen_rtx_LO_SUM (Pmode, hi, copy_rtx (tocrel));
|
||||
}
|
||||
else
|
||||
return gen_rtx_PLUS (Pmode, tocreg, tocrel);
|
||||
}
|
||||
|
||||
/* Issue assembly directives that create a reference to the given DWARF
|
||||
|
@ -293,6 +293,20 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
|
||||
#define TARGET_SECURE_PLT 0
|
||||
#endif
|
||||
|
||||
/* Code model for 64-bit linux.
|
||||
small: 16-bit toc offsets.
|
||||
medium: 32-bit toc offsets, static data and code within 2G of TOC pointer.
|
||||
large: 32-bit toc offsets, no limit on static data and code. */
|
||||
enum rs6000_cmodel {
|
||||
CMODEL_SMALL,
|
||||
CMODEL_MEDIUM,
|
||||
CMODEL_LARGE
|
||||
};
|
||||
|
||||
#ifndef TARGET_CMODEL
|
||||
#define TARGET_CMODEL CMODEL_SMALL
|
||||
#endif
|
||||
|
||||
#define TARGET_32BIT (! TARGET_64BIT)
|
||||
|
||||
#ifndef HAVE_AS_TLS
|
||||
|
@ -11004,7 +11004,12 @@
|
||||
UNSPEC_TLSGD)
|
||||
(clobber (reg:SI LR_REGNO))]
|
||||
"HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX"
|
||||
"addi %0,%1,%2@got@tlsgd\;bl %z3\;%."
|
||||
{
|
||||
if (TARGET_CMODEL != CMODEL_SMALL)
|
||||
return "addis %0,%1,%2@got@tlsgd@ha\;addi %0,%0,%2@got@tlsgd@l\;bl %z3\;%.";
|
||||
else
|
||||
return "addi %0,%1,%2@got@tlsgd\;bl %z3\;%.";
|
||||
}
|
||||
"&& TARGET_TLS_MARKERS"
|
||||
[(set (match_dup 0)
|
||||
(unspec:TLSmode [(match_dup 1)
|
||||
@ -11017,7 +11022,10 @@
|
||||
(clobber (reg:SI LR_REGNO))])]
|
||||
""
|
||||
[(set_attr "type" "two")
|
||||
(set_attr "length" "12")])
|
||||
(set (attr "length")
|
||||
(if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
|
||||
(const_int 16)
|
||||
(const_int 12)))])
|
||||
|
||||
(define_insn_and_split "tls_gd_sysv<TLSmode:tls_sysv_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
|
||||
@ -11053,13 +11061,47 @@
|
||||
[(set_attr "type" "two")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
(define_insn "*tls_gd<TLSmode:tls_abi_suffix>"
|
||||
(define_insn_and_split "*tls_gd<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
|
||||
(unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
|
||||
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
|
||||
UNSPEC_TLSGD))]
|
||||
"HAVE_AS_TLS && TARGET_TLS_MARKERS"
|
||||
"addi %0,%1,%2@got@tlsgd"
|
||||
"&& TARGET_CMODEL != CMODEL_SMALL"
|
||||
[(set (match_dup 3)
|
||||
(plus:TLSmode (match_dup 1)
|
||||
(high:TLSmode
|
||||
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD))))
|
||||
(set (match_dup 0)
|
||||
(lo_sum:TLSmode (match_dup 3)
|
||||
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)))]
|
||||
"
|
||||
{
|
||||
operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
|
||||
}"
|
||||
[(set (attr "length")
|
||||
(if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
|
||||
(const_int 8)
|
||||
(const_int 4)))])
|
||||
|
||||
(define_insn "*tls_gd_high<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
|
||||
(plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
|
||||
(high:TLSmode
|
||||
(unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
|
||||
UNSPEC_TLSGD))))]
|
||||
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
|
||||
"addis %0,%1,%2@got@tlsgd@ha"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*tls_gd_low<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
|
||||
(lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
|
||||
(unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
|
||||
UNSPEC_TLSGD)))]
|
||||
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
|
||||
"addi %0,%1,%2@got@tlsgd@l"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*tls_gd_call_aix<TLSmode:tls_abi_suffix>"
|
||||
@ -11102,7 +11144,12 @@
|
||||
UNSPEC_TLSLD)
|
||||
(clobber (reg:SI LR_REGNO))]
|
||||
"HAVE_AS_TLS && DEFAULT_ABI == ABI_AIX"
|
||||
"addi %0,%1,%&@got@tlsld\;bl %z2\;%."
|
||||
{
|
||||
if (TARGET_CMODEL != CMODEL_SMALL)
|
||||
return "addis %0,%1,%&@got@tlsld@ha\;addi %0,%0,%&@got@tlsld@l\;bl %z2\;%.";
|
||||
else
|
||||
return "addi %0,%1,%&@got@tlsld\;bl %z2\;%.";
|
||||
}
|
||||
"&& TARGET_TLS_MARKERS"
|
||||
[(set (match_dup 0)
|
||||
(unspec:TLSmode [(match_dup 1)]
|
||||
@ -11113,7 +11160,11 @@
|
||||
(unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)
|
||||
(clobber (reg:SI LR_REGNO))])]
|
||||
""
|
||||
[(set_attr "length" "12")])
|
||||
[(set_attr "type" "two")
|
||||
(set (attr "length")
|
||||
(if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
|
||||
(const_int 16)
|
||||
(const_int 12)))])
|
||||
|
||||
(define_insn_and_split "tls_ld_sysv<TLSmode:tls_sysv_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
|
||||
@ -11146,12 +11197,44 @@
|
||||
""
|
||||
[(set_attr "length" "8")])
|
||||
|
||||
(define_insn "*tls_ld<TLSmode:tls_abi_suffix>"
|
||||
(define_insn_and_split "*tls_ld<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
|
||||
(unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")]
|
||||
UNSPEC_TLSLD))]
|
||||
"HAVE_AS_TLS && TARGET_TLS_MARKERS"
|
||||
"addi %0,%1,%&@got@tlsld"
|
||||
"&& TARGET_CMODEL != CMODEL_SMALL"
|
||||
[(set (match_dup 2)
|
||||
(plus:TLSmode (match_dup 1)
|
||||
(high:TLSmode
|
||||
(unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD))))
|
||||
(set (match_dup 0)
|
||||
(lo_sum:TLSmode (match_dup 2)
|
||||
(unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))]
|
||||
"
|
||||
{
|
||||
operands[2] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
|
||||
}"
|
||||
[(set (attr "length")
|
||||
(if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
|
||||
(const_int 8)
|
||||
(const_int 4)))])
|
||||
|
||||
(define_insn "*tls_ld_high<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
|
||||
(plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
|
||||
(high:TLSmode
|
||||
(unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD))))]
|
||||
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
|
||||
"addis %0,%1,%&@got@tlsld@ha"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*tls_ld_low<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
|
||||
(lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
|
||||
(unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))]
|
||||
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
|
||||
"addi %0,%1,%&@got@tlsld@l"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*tls_ld_call_aix<TLSmode:tls_abi_suffix>"
|
||||
@ -11208,13 +11291,48 @@
|
||||
"HAVE_AS_TLS"
|
||||
"addi %0,%1,%2@dtprel@l")
|
||||
|
||||
(define_insn "tls_got_dtprel_<TLSmode:tls_abi_suffix>"
|
||||
(define_insn_and_split "tls_got_dtprel_<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
|
||||
(unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
|
||||
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
|
||||
UNSPEC_TLSGOTDTPREL))]
|
||||
"HAVE_AS_TLS"
|
||||
"l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel(%1)")
|
||||
"l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel(%1)"
|
||||
"&& TARGET_CMODEL != CMODEL_SMALL"
|
||||
[(set (match_dup 3)
|
||||
(plus:TLSmode (match_dup 1)
|
||||
(high:TLSmode
|
||||
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL))))
|
||||
(set (match_dup 0)
|
||||
(lo_sum:TLSmode (match_dup 3)
|
||||
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL)))]
|
||||
"
|
||||
{
|
||||
operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
|
||||
}"
|
||||
[(set (attr "length")
|
||||
(if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
|
||||
(const_int 8)
|
||||
(const_int 4)))])
|
||||
|
||||
(define_insn "*tls_got_dtprel_high<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
|
||||
(plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
|
||||
(high:TLSmode
|
||||
(unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
|
||||
UNSPEC_TLSGOTDTPREL))))]
|
||||
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
|
||||
"addis %0,%1,%2@got@dtprel@ha"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*tls_got_dtprel_low<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
|
||||
(lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
|
||||
(unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
|
||||
UNSPEC_TLSGOTDTPREL)))]
|
||||
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
|
||||
"l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel@l(%1)"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_insn "tls_tprel_<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
|
||||
@ -11243,13 +11361,48 @@
|
||||
;; "b" output constraint here and on tls_tls input to support linker tls
|
||||
;; optimization. The linker may edit the instructions emitted by a
|
||||
;; tls_got_tprel/tls_tls pair to addis,addi.
|
||||
(define_insn "tls_got_tprel_<TLSmode:tls_abi_suffix>"
|
||||
(define_insn_and_split "tls_got_tprel_<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
|
||||
(unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
|
||||
(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
|
||||
UNSPEC_TLSGOTTPREL))]
|
||||
"HAVE_AS_TLS"
|
||||
"l<TLSmode:tls_insn_suffix> %0,%2@got@tprel(%1)")
|
||||
"l<TLSmode:tls_insn_suffix> %0,%2@got@tprel(%1)"
|
||||
"&& TARGET_CMODEL != CMODEL_SMALL"
|
||||
[(set (match_dup 3)
|
||||
(plus:TLSmode (match_dup 1)
|
||||
(high:TLSmode
|
||||
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL))))
|
||||
(set (match_dup 0)
|
||||
(lo_sum:TLSmode (match_dup 3)
|
||||
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL)))]
|
||||
"
|
||||
{
|
||||
operands[3] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
|
||||
}"
|
||||
[(set (attr "length")
|
||||
(if_then_else (ne (symbol_ref "TARGET_CMODEL") (symbol_ref "CMODEL_SMALL"))
|
||||
(const_int 8)
|
||||
(const_int 4)))])
|
||||
|
||||
(define_insn "*tls_got_tprel_high<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
|
||||
(plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
|
||||
(high:TLSmode
|
||||
(unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
|
||||
UNSPEC_TLSGOTTPREL))))]
|
||||
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
|
||||
"addis %0,%1,%2@got@tprel@ha"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*tls_got_tprel_low<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
|
||||
(lo_sum:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
|
||||
(unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
|
||||
UNSPEC_TLSGOTTPREL)))]
|
||||
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
|
||||
"l<TLSmode:tls_insn_suffix> %0,%2@got@tprel@l(%1)"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_insn "tls_tls_<TLSmode:tls_abi_suffix>"
|
||||
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=r")
|
||||
@ -11258,7 +11411,6 @@
|
||||
UNSPEC_TLSTLS))]
|
||||
"HAVE_AS_TLS"
|
||||
"add %0,%1,%2@tls")
|
||||
|
||||
|
||||
;; Next come insns related to the calling sequence.
|
||||
;;
|
||||
@ -11548,6 +11700,21 @@
|
||||
"@
|
||||
{cal|la} %0,%2@l(%1)
|
||||
{ai|addic} %0,%1,%K2")
|
||||
|
||||
;; Largetoc support
|
||||
(define_insn "largetoc_high"
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "=b")
|
||||
(plus:DI (match_operand:DI 1 "gpc_reg_operand" "b")
|
||||
(high:DI (match_operand:DI 2 "" ""))))]
|
||||
"TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
|
||||
"{cau|addis} %0,%1,%2@ha")
|
||||
|
||||
(define_insn "largetoc_low"
|
||||
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
|
||||
(lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b")
|
||||
(match_operand:DI 2 "" "")))]
|
||||
"TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
|
||||
"{cal %0,%2@l(%1)|addi %0,%1,%2@l}")
|
||||
|
||||
;; A function pointer under AIX is a pointer to a data area whose first word
|
||||
;; contains the actual address of the function, whose second word contains a
|
||||
@ -12822,26 +12989,27 @@
|
||||
(clobber (match_scratch:DF 7 "=d"))
|
||||
(clobber (match_scratch:DF 8 "=d"))
|
||||
(clobber (match_scratch:DF 9 "=d"))
|
||||
(clobber (match_scratch:DF 10 "=d"))]
|
||||
(clobber (match_scratch:DF 10 "=d"))
|
||||
(clobber (match_scratch:GPR 11 "=b"))]
|
||||
"!TARGET_IEEEQUAD && TARGET_XL_COMPAT
|
||||
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 3) (match_dup 13))
|
||||
(set (match_dup 4) (match_dup 14))
|
||||
[(set (match_dup 3) (match_dup 14))
|
||||
(set (match_dup 4) (match_dup 15))
|
||||
(set (match_dup 9) (abs:DF (match_dup 5)))
|
||||
(set (match_dup 0) (compare:CCFP (match_dup 9) (match_dup 3)))
|
||||
(set (pc) (if_then_else (ne (match_dup 0) (const_int 0))
|
||||
(label_ref (match_dup 11))
|
||||
(label_ref (match_dup 12))
|
||||
(pc)))
|
||||
(set (match_dup 0) (compare:CCFP (match_dup 5) (match_dup 7)))
|
||||
(set (pc) (label_ref (match_dup 12)))
|
||||
(match_dup 11)
|
||||
(set (pc) (label_ref (match_dup 13)))
|
||||
(match_dup 12)
|
||||
(set (match_dup 10) (minus:DF (match_dup 5) (match_dup 7)))
|
||||
(set (match_dup 9) (minus:DF (match_dup 6) (match_dup 8)))
|
||||
(set (match_dup 9) (plus:DF (match_dup 10) (match_dup 9)))
|
||||
(set (match_dup 0) (compare:CCFP (match_dup 9) (match_dup 4)))
|
||||
(match_dup 12)]
|
||||
(match_dup 13)]
|
||||
{
|
||||
REAL_VALUE_TYPE rv;
|
||||
const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
|
||||
@ -12851,22 +13019,23 @@
|
||||
operands[6] = simplify_gen_subreg (DFmode, operands[1], TFmode, lo_word);
|
||||
operands[7] = simplify_gen_subreg (DFmode, operands[2], TFmode, hi_word);
|
||||
operands[8] = simplify_gen_subreg (DFmode, operands[2], TFmode, lo_word);
|
||||
operands[11] = gen_label_rtx ();
|
||||
operands[12] = gen_label_rtx ();
|
||||
operands[13] = gen_label_rtx ();
|
||||
real_inf (&rv);
|
||||
operands[13] = force_const_mem (DFmode,
|
||||
CONST_DOUBLE_FROM_REAL_VALUE (rv, DFmode));
|
||||
operands[14] = force_const_mem (DFmode,
|
||||
CONST_DOUBLE_FROM_REAL_VALUE (rv, DFmode));
|
||||
operands[15] = force_const_mem (DFmode,
|
||||
CONST_DOUBLE_FROM_REAL_VALUE (dconst0,
|
||||
DFmode));
|
||||
if (TARGET_TOC)
|
||||
{
|
||||
operands[13] = gen_const_mem (DFmode,
|
||||
create_TOC_reference (XEXP (operands[13], 0)));
|
||||
operands[14] = gen_const_mem (DFmode,
|
||||
create_TOC_reference (XEXP (operands[14], 0)));
|
||||
set_mem_alias_set (operands[13], get_TOC_alias_set ());
|
||||
rtx tocref;
|
||||
tocref = create_TOC_reference (XEXP (operands[14], 0), operands[11]);
|
||||
operands[14] = gen_const_mem (DFmode, tocref);
|
||||
tocref = create_TOC_reference (XEXP (operands[15], 0), operands[11]);
|
||||
operands[15] = gen_const_mem (DFmode, tocref);
|
||||
set_mem_alias_set (operands[14], get_TOC_alias_set ());
|
||||
set_mem_alias_set (operands[15], get_TOC_alias_set ());
|
||||
}
|
||||
})
|
||||
|
||||
|
37
gcc/configure
vendored
37
gcc/configure
vendored
@ -24843,6 +24843,43 @@ $as_echo "$gcc_cv_ld_no_dot_syms" >&6; }
|
||||
|
||||
$as_echo "#define HAVE_LD_NO_DOT_SYMS 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker large toc support" >&5
|
||||
$as_echo_n "checking linker large toc support... " >&6; }
|
||||
if test "${gcc_cv_ld_large_toc+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
gcc_cv_ld_large_toc=no
|
||||
if test $in_tree_ld = yes ; then
|
||||
if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2; then
|
||||
gcc_cv_ld_large_toc=yes
|
||||
fi
|
||||
elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
|
||||
cat > conftest.s <<EOF
|
||||
.section ".tbss","awT",@nobits
|
||||
.align 3
|
||||
ie0: .space 8
|
||||
.global _start
|
||||
.text
|
||||
_start:
|
||||
addis 9,13,ie0@got@tprel@ha
|
||||
ld 9,ie0@got@tprel@l(9)
|
||||
EOF
|
||||
if $gcc_cv_as -a64 -o conftest.o conftest.s > /dev/null 2>&1 \
|
||||
&& $gcc_cv_ld -melf64ppc --no-toc-sort -o conftest conftest.o > /dev/null 2>&1; then
|
||||
gcc_cv_ld_large_toc=yes
|
||||
fi
|
||||
rm -f conftest conftest.o conftest.s
|
||||
fi
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_large_toc" >&5
|
||||
$as_echo "$gcc_cv_ld_large_toc" >&6; }
|
||||
if test x"$gcc_cv_ld_large_toc" = xyes; then
|
||||
|
||||
$as_echo "#define HAVE_LD_LARGE_TOC 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
@ -3996,6 +3996,36 @@ EOF
|
||||
AC_DEFINE(HAVE_LD_NO_DOT_SYMS, 1,
|
||||
[Define if your PowerPC64 linker only needs function descriptor syms.])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK(linker large toc support,
|
||||
gcc_cv_ld_large_toc,
|
||||
[gcc_cv_ld_large_toc=no
|
||||
if test $in_tree_ld = yes ; then
|
||||
if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2; then
|
||||
gcc_cv_ld_large_toc=yes
|
||||
fi
|
||||
elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
|
||||
cat > conftest.s <<EOF
|
||||
.section ".tbss","awT",@nobits
|
||||
.align 3
|
||||
ie0: .space 8
|
||||
.global _start
|
||||
.text
|
||||
_start:
|
||||
addis 9,13,ie0@got@tprel@ha
|
||||
ld 9,ie0@got@tprel@l(9)
|
||||
EOF
|
||||
if $gcc_cv_as -a64 -o conftest.o conftest.s > /dev/null 2>&1 \
|
||||
&& $gcc_cv_ld -melf64ppc --no-toc-sort -o conftest conftest.o > /dev/null 2>&1; then
|
||||
gcc_cv_ld_large_toc=yes
|
||||
fi
|
||||
rm -f conftest conftest.o conftest.s
|
||||
fi
|
||||
])
|
||||
if test x"$gcc_cv_ld_large_toc" = xyes; then
|
||||
AC_DEFINE(HAVE_LD_LARGE_TOC, 1,
|
||||
[Define if your PowerPC64 linker supports a large TOC.])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -744,6 +744,7 @@ See RS/6000 and PowerPC Options.
|
||||
@emph{RS/6000 and PowerPC Options}
|
||||
@gccoptlist{-mcpu=@var{cpu-type} @gol
|
||||
-mtune=@var{cpu-type} @gol
|
||||
-mcmodel=@var{code-model} @gol
|
||||
-mpower -mno-power -mpower2 -mno-power2 @gol
|
||||
-mpowerpc -mpowerpc64 -mno-powerpc @gol
|
||||
-maltivec -mno-altivec @gol
|
||||
@ -14967,6 +14968,22 @@ values for @var{cpu_type} are used for @option{-mtune} as for
|
||||
architecture, registers, and mnemonics set by @option{-mcpu}, but the
|
||||
scheduling parameters set by @option{-mtune}.
|
||||
|
||||
@item -mcmodel=small
|
||||
@opindex mcmodel=small
|
||||
Generate PowerPC64 code for the small model: The TOC is limited to
|
||||
64k.
|
||||
|
||||
@item -mcmodel=medium
|
||||
@opindex mcmodel=medium
|
||||
Generate PowerPC64 code for the medium model: The TOC and other static
|
||||
data may be up to a total of 4G in size.
|
||||
|
||||
@item -mcmodel=large
|
||||
@opindex mcmodel=large
|
||||
Generate PowerPC64 code for the large model: The TOC may be up to 4G
|
||||
in size. Other data and code is only limited by the 64-bit address
|
||||
space.
|
||||
|
||||
@item -maltivec
|
||||
@itemx -mno-altivec
|
||||
@opindex maltivec
|
||||
|
Loading…
Reference in New Issue
Block a user