Commit 8afc3636 by Alan Modra Committed by Alan Modra

predicates.md (input_operand): Don't match constant pool addresses.

	* config/rs6000/predicates.md (input_operand): Don't match
	constant pool addresses.  Remove label_ref, high and plus from
	match_code list.  Remove redundant CONSTANT_P test.
	(splat_input_operand): Similarly update match_code list.
	(small_toc_ref): New predicate.
	* config/rs6000/rs6000-protos.h (toc_relative_expr_p): Update prototype.
	* config/rs6000/rs6000.c (tocrel_base, tocrel_offset): Make const.
	(legitimate_constant_pool_address_p): Move TARGET_TOC test and
	register checks to..
	(toc_relative_expr_p): ..here.  Add "strict" param.  Match new rtl
	generated by create_TOC_reference.
	(rs6000_legitimize_address): Update cerate_TOC_reference call.
	(rs6000_delegitimize_address): Handle new rtl for toc refs.
	(rs6000_cannot_force_const_mem, rs6000_find_base_term): Likewise.
	(use_toc_relative_ref): New function, split out from..
	(rs6000_emit_move): ..here.  Remove redundant tests.  Update
	create_TOC_reference calls.
	(rs6000_legitimize_reload_address): Formatting.  Handle splitting
	of medium/large model toc addresses.  Use use_toc_relative_ref.
	(print_operand): Formatting, style.  Adjust for toc changes.
	(print_operand_address): Likewise.
	(rs6000_output_addr_const_extra): Likewise.
	(create_TOC_reference): Put TOC_REGISTER in UNSPEC_TOCREL rather
	than a PLUS.  Use this formulation for both high and low part
	of -mcmodel=medium/large toc reference too.  Before reload,
	always use the small model formulation.
	* config/rs6000/rs6000.md (tls_gd, tls_gd_high): Similarly avoid
	a PLUS in high part of addresses here.
	(tls_ld, tls_ld_high, tls_got_dtprel, tls_got_dtprel_high): Likewise.
	(tls_got_tprel, tls_got_tprel_high, largetoc_high): Likewise.
	(largetoc_high, largetoc_low): Move earlier.  Cope when no
	base reg available.
	(largetoc_high_plus): New insn.
	(movsi_internal1, movsi_internal1_single, movsf_softfloat,
	movdi_mfpgpr, movdi_internal64): Don't handle 'R' constraint here..
	(tocref): ..instead do so here, new insn and split.

From-SVN: r187699
parent d1925759
2012-05-21 Alan Modra <amodra@gmail.com>
* config/rs6000/predicates.md (input_operand): Don't match
constant pool addresses. Remove label_ref, high and plus from
match_code list. Remove redundant CONSTANT_P test.
(splat_input_operand): Similarly update match_code list.
(small_toc_ref): New predicate.
* config/rs6000/rs6000-protos.h (toc_relative_expr_p): Update prototype.
* config/rs6000/rs6000.c (tocrel_base, tocrel_offset): Make const.
(legitimate_constant_pool_address_p): Move TARGET_TOC test and
register checks to..
(toc_relative_expr_p): ..here. Add "strict" param. Match new rtl
generated by create_TOC_reference.
(rs6000_legitimize_address): Update cerate_TOC_reference call.
(rs6000_delegitimize_address): Handle new rtl for toc refs.
(rs6000_cannot_force_const_mem, rs6000_find_base_term): Likewise.
(use_toc_relative_ref): New function, split out from..
(rs6000_emit_move): ..here. Remove redundant tests. Update
create_TOC_reference calls.
(rs6000_legitimize_reload_address): Formatting. Handle splitting
of medium/large model toc addresses. Use use_toc_relative_ref.
(print_operand): Formatting, style. Adjust for toc changes.
(print_operand_address): Likewise.
(rs6000_output_addr_const_extra): Likewise.
(create_TOC_reference): Put TOC_REGISTER in UNSPEC_TOCREL rather
than a PLUS. Use this formulation for both high and low part
of -mcmodel=medium/large toc reference too. Before reload,
always use the small model formulation.
* config/rs6000/rs6000.md (tls_gd, tls_gd_high): Similarly avoid
a PLUS in high part of addresses here.
(tls_ld, tls_ld_high, tls_got_dtprel, tls_got_dtprel_high): Likewise.
(tls_got_tprel, tls_got_tprel_high, largetoc_high): Likewise.
(largetoc_high, largetoc_low): Move earlier. Cope when no
base reg available.
(largetoc_high_plus): New insn.
(movsi_internal1, movsi_internal1_single, movsf_softfloat,
movdi_mfpgpr, movdi_internal64): Don't handle 'R' constraint here..
(tocref): ..instead do so here, new insn and split.
2012-05-20 H.J. Lu <hongjiu.lu@intel.com> 2012-05-20 H.J. Lu <hongjiu.lu@intel.com>
* config/i386/driver-i386.c (host_detect_local_cpu): Support * config/i386/driver-i386.c (host_detect_local_cpu): Support
......
;; Predicate definitions for POWER and PowerPC. ;; Predicate definitions for POWER and PowerPC.
;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 ;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
;; Free Software Foundation, Inc. ;; Free Software Foundation, Inc.
;; ;;
;; This file is part of GCC. ;; This file is part of GCC.
...@@ -824,8 +824,8 @@ ...@@ -824,8 +824,8 @@
;; Return 1 if this operand is a valid input for a move insn. ;; Return 1 if this operand is a valid input for a move insn.
(define_predicate "input_operand" (define_predicate "input_operand"
(match_code "label_ref,symbol_ref,const,high,reg,subreg,mem, (match_code "symbol_ref,const,reg,subreg,mem,
const_double,const_vector,const_int,plus") const_double,const_vector,const_int")
{ {
/* Memory is always valid. */ /* Memory is always valid. */
if (memory_operand (op, mode)) if (memory_operand (op, mode))
...@@ -833,7 +833,6 @@ ...@@ -833,7 +833,6 @@
/* For floating-point, easy constants are valid. */ /* For floating-point, easy constants are valid. */
if (SCALAR_FLOAT_MODE_P (mode) if (SCALAR_FLOAT_MODE_P (mode)
&& CONSTANT_P (op)
&& easy_fp_constant (op, mode)) && easy_fp_constant (op, mode))
return 1; return 1;
...@@ -866,14 +865,6 @@ ...@@ -866,14 +865,6 @@
if (register_operand (op, mode)) if (register_operand (op, mode))
return 1; return 1;
/* A SYMBOL_REF referring to the TOC is valid. */
if (legitimate_constant_pool_address_p (op, mode, false))
return 1;
/* A constant pool expression (relative to the TOC) is valid */
if (toc_relative_expr_p (op))
return 1;
/* V.4 allows SYMBOL_REFs and CONSTs that are in the small data region /* V.4 allows SYMBOL_REFs and CONSTs that are in the small data region
to be valid. */ to be valid. */
if (DEFAULT_ABI == ABI_V4 if (DEFAULT_ABI == ABI_V4
...@@ -886,8 +877,8 @@ ...@@ -886,8 +877,8 @@
;; Return 1 if this operand is a valid input for a vsx_splat insn. ;; Return 1 if this operand is a valid input for a vsx_splat insn.
(define_predicate "splat_input_operand" (define_predicate "splat_input_operand"
(match_code "label_ref,symbol_ref,const,high,reg,subreg,mem, (match_code "symbol_ref,const,reg,subreg,mem,
const_double,const_vector,const_int,plus") const_double,const_vector,const_int")
{ {
if (MEM_P (op)) if (MEM_P (op))
{ {
...@@ -1461,3 +1452,14 @@ ...@@ -1461,3 +1452,14 @@
&& GET_MODE (XEXP (XVECEXP (op, 0, 0), 0)) == BLKmode && GET_MODE (XEXP (XVECEXP (op, 0, 0), 0)) == BLKmode
&& XEXP (XVECEXP (op, 0, 0), 1) == const0_rtx); && XEXP (XVECEXP (op, 0, 0), 1) == const0_rtx);
}) })
;; Match a small code model toc reference (or medium and large
;; model toc references before reload).
(define_predicate "small_toc_ref"
(match_code "unspec,plus")
{
if (GET_CODE (op) == PLUS && CONST_INT_P (XEXP (op, 1)))
op = XEXP (op, 0);
return GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_TOCREL;
})
/* Definitions of target machine for GNU compiler, for IBM RS/6000. /* Definitions of target machine for GNU compiler, for IBM RS/6000.
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010, 2011 2010, 2011, 2012
Free Software Foundation, Inc. Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
...@@ -38,7 +38,7 @@ extern bool macho_lo_sum_memory_operand (rtx, enum machine_mode); ...@@ -38,7 +38,7 @@ extern bool macho_lo_sum_memory_operand (rtx, enum machine_mode);
extern int num_insns_constant (rtx, enum machine_mode); extern int num_insns_constant (rtx, enum machine_mode);
extern int num_insns_constant_wide (HOST_WIDE_INT); extern int num_insns_constant_wide (HOST_WIDE_INT);
extern int small_data_operand (rtx, enum machine_mode); extern int small_data_operand (rtx, enum machine_mode);
extern bool toc_relative_expr_p (rtx); extern bool toc_relative_expr_p (const_rtx, bool);
extern bool invalid_e500_subreg (rtx, enum machine_mode); extern bool invalid_e500_subreg (rtx, enum machine_mode);
extern void validate_condition_mode (enum rtx_code, enum machine_mode); extern void validate_condition_mode (enum rtx_code, enum machine_mode);
extern bool legitimate_constant_pool_address_p (const_rtx, enum machine_mode, extern bool legitimate_constant_pool_address_p (const_rtx, enum machine_mode,
......
...@@ -5307,15 +5307,37 @@ constant_pool_expr_p (rtx op) ...@@ -5307,15 +5307,37 @@ constant_pool_expr_p (rtx op)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (base), Pmode)); && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (base), Pmode));
} }
static rtx tocrel_base, tocrel_offset; static const_rtx tocrel_base, tocrel_offset;
/* Return true if OP is a toc pointer relative address (the output
of create_TOC_reference). If STRICT, do not match high part or
non-split -mcmodel=large/medium toc pointer relative addresses. */
bool bool
toc_relative_expr_p (rtx op) toc_relative_expr_p (const_rtx op, bool strict)
{ {
if (GET_CODE (op) != CONST) if (!TARGET_TOC)
return false;
if (TARGET_CMODEL != CMODEL_SMALL)
{
/* Only match the low part. */
if (GET_CODE (op) == LO_SUM
&& REG_P (XEXP (op, 0))
&& INT_REG_OK_FOR_BASE_P (XEXP (op, 0), strict))
op = XEXP (op, 1);
else if (strict)
return false; return false;
}
tocrel_base = op;
tocrel_offset = const0_rtx;
if (GET_CODE (op) == PLUS && CONST_INT_P (XEXP (op, 1)))
{
tocrel_base = XEXP (op, 0);
tocrel_offset = XEXP (op, 1);
}
split_const (op, &tocrel_base, &tocrel_offset);
return (GET_CODE (tocrel_base) == UNSPEC return (GET_CODE (tocrel_base) == UNSPEC
&& XINT (tocrel_base, 1) == UNSPEC_TOCREL); && XINT (tocrel_base, 1) == UNSPEC_TOCREL);
} }
...@@ -5327,14 +5349,7 @@ bool ...@@ -5327,14 +5349,7 @@ bool
legitimate_constant_pool_address_p (const_rtx x, enum machine_mode mode, legitimate_constant_pool_address_p (const_rtx x, enum machine_mode mode,
bool strict) bool strict)
{ {
return (TARGET_TOC return (toc_relative_expr_p (x, strict)
&& (GET_CODE (x) == PLUS || GET_CODE (x) == LO_SUM)
&& GET_CODE (XEXP (x, 0)) == REG
&& (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))
&& (TARGET_CMODEL != CMODEL_MEDIUM && (TARGET_CMODEL != CMODEL_MEDIUM
|| constant_pool_expr_p (XVECEXP (tocrel_base, 0, 0)) || constant_pool_expr_p (XVECEXP (tocrel_base, 0, 0))
|| mode == QImode || mode == QImode
...@@ -5714,10 +5729,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -5714,10 +5729,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
&& GET_CODE (x) == SYMBOL_REF && GET_CODE (x) == SYMBOL_REF
&& constant_pool_expr_p (x) && constant_pool_expr_p (x)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode)) && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
{ return create_TOC_reference (x, NULL_RTX);
rtx reg = TARGET_CMODEL != CMODEL_SMALL ? gen_reg_rtx (Pmode) : NULL_RTX;
return create_TOC_reference (x, reg);
}
else else
return x; return x;
} }
...@@ -5800,19 +5812,19 @@ rs6000_output_dwarf_dtprel (FILE *file, int size, rtx x) ...@@ -5800,19 +5812,19 @@ rs6000_output_dwarf_dtprel (FILE *file, int size, rtx x)
static rtx static rtx
rs6000_delegitimize_address (rtx orig_x) rs6000_delegitimize_address (rtx orig_x)
{ {
rtx x, y; rtx x, y, offset;
orig_x = delegitimize_mem_from_attrs (orig_x); orig_x = delegitimize_mem_from_attrs (orig_x);
x = orig_x; x = orig_x;
if (MEM_P (x)) if (MEM_P (x))
x = XEXP (x, 0); x = XEXP (x, 0);
if (GET_CODE (x) == (TARGET_CMODEL != CMODEL_SMALL ? LO_SUM : PLUS) y = x;
&& GET_CODE (XEXP (x, 1)) == CONST) if (TARGET_CMODEL != CMODEL_SMALL
{ && GET_CODE (y) == LO_SUM)
rtx offset = NULL_RTX; y = XEXP (y, 1);
y = XEXP (XEXP (x, 1), 0); offset = NULL_RTX;
if (GET_CODE (y) == PLUS if (GET_CODE (y) == PLUS
&& GET_MODE (y) == Pmode && GET_MODE (y) == Pmode
&& CONST_INT_P (XEXP (y, 1))) && CONST_INT_P (XEXP (y, 1)))
...@@ -5820,21 +5832,28 @@ rs6000_delegitimize_address (rtx orig_x) ...@@ -5820,21 +5832,28 @@ rs6000_delegitimize_address (rtx orig_x)
offset = XEXP (y, 1); offset = XEXP (y, 1);
y = XEXP (y, 0); y = XEXP (y, 0);
} }
if (GET_CODE (y) == UNSPEC if (GET_CODE (y) == UNSPEC
&& XINT (y, 1) == UNSPEC_TOCREL && XINT (y, 1) == UNSPEC_TOCREL)
&& ((GET_CODE (XEXP (x, 0)) == REG {
&& (REGNO (XEXP (x, 0)) == TOC_REGISTER #ifdef ENABLE_CHECKING
|| TARGET_MINIMAL_TOC if (REG_P (XVECEXP (y, 0, 1))
|| TARGET_CMODEL != CMODEL_SMALL)) && REGNO (XVECEXP (y, 0, 1)) == TOC_REGISTER)
|| (TARGET_CMODEL != CMODEL_SMALL {
&& GET_CODE (XEXP (x, 0)) == CONST /* All good. */
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS }
&& GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == REG else if (GET_CODE (XVECEXP (y, 0, 1)) == DEBUG_EXPR)
&& REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0)) == TOC_REGISTER {
&& GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == HIGH /* Weirdness alert. df_note_compute can replace r2 with a
&& rtx_equal_p (XEXP (x, 1), debug_expr when this unspec is in a debug_insn.
XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0))))) Seen in gcc.dg/pr51957-1.c */
}
else
{ {
debug_rtx (orig_x);
abort ();
}
#endif
y = XVECEXP (y, 0, 0); y = XVECEXP (y, 0, 0);
if (offset != NULL_RTX) if (offset != NULL_RTX)
y = gen_rtx_PLUS (Pmode, y, offset); y = gen_rtx_PLUS (Pmode, y, offset);
...@@ -5843,7 +5862,6 @@ rs6000_delegitimize_address (rtx orig_x) ...@@ -5843,7 +5862,6 @@ rs6000_delegitimize_address (rtx orig_x)
else else
return replace_equiv_address_nv (orig_x, y); return replace_equiv_address_nv (orig_x, y);
} }
}
if (TARGET_MACHO if (TARGET_MACHO
&& GET_CODE (orig_x) == LO_SUM && GET_CODE (orig_x) == LO_SUM
...@@ -6104,9 +6122,8 @@ rs6000_tls_referenced_p (rtx x) ...@@ -6104,9 +6122,8 @@ rs6000_tls_referenced_p (rtx x)
static bool static bool
rs6000_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) rs6000_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
{ {
if (GET_CODE (x) == CONST if (GET_CODE (x) == HIGH
&& GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (x, 0)) == UNSPEC)
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH)
return true; return true;
return rs6000_tls_referenced_p (x); return rs6000_tls_referenced_p (x);
...@@ -6121,6 +6138,21 @@ rs6000_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED) ...@@ -6121,6 +6138,21 @@ rs6000_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
return RS6000_SYMBOL_REF_TLS_P (*x); return RS6000_SYMBOL_REF_TLS_P (*x);
} }
/* Return true iff the given SYMBOL_REF refers to a constant pool entry
that we have put in the TOC, or for cmodel=medium, if the SYMBOL_REF
can be addressed relative to the toc pointer. */
static bool
use_toc_relative_ref (rtx sym)
{
return ((constant_pool_expr_p (sym)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (sym),
get_pool_mode (sym)))
|| (TARGET_CMODEL == CMODEL_MEDIUM
&& !CONSTANT_POOL_ADDRESS_P (sym)
&& SYMBOL_REF_LOCAL_P (sym)));
}
/* Our implementation of LEGITIMIZE_RELOAD_ADDRESS. Returns a value to /* Our implementation of LEGITIMIZE_RELOAD_ADDRESS. Returns a value to
replace the input X, or the original X if no replacement is called for. replace the input X, or the original X if no replacement is called for.
The output parameter *WIN is 1 if the calling macro should goto WIN, The output parameter *WIN is 1 if the calling macro should goto WIN,
...@@ -6158,7 +6190,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, ...@@ -6158,7 +6190,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
{ {
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
opnum, (enum reload_type)type); opnum, (enum reload_type) type);
*win = 1; *win = 1;
return x; return x;
} }
...@@ -6169,7 +6201,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, ...@@ -6169,7 +6201,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
{ {
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
opnum, (enum reload_type)type); opnum, (enum reload_type) type);
*win = 1; *win = 1;
return x; return x;
} }
...@@ -6187,24 +6219,18 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, ...@@ -6187,24 +6219,18 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
floating point constant. */ floating point constant. */
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
opnum, (enum reload_type)type); opnum, (enum reload_type) type);
*win = 1; *win = 1;
return x; return x;
} }
#endif #endif
if (TARGET_CMODEL != CMODEL_SMALL if (TARGET_CMODEL != CMODEL_SMALL
&& GET_CODE (x) == LO_SUM && reg_offset_p
&& GET_CODE (XEXP (x, 0)) == PLUS && small_toc_ref (x, VOIDmode))
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
&& REGNO (XEXP (XEXP (x, 0), 0)) == TOC_REGISTER
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST
&& GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == 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 (XEXP (x, 0), 1), 0), 0), XEXP (x, 1)))
{ {
rtx hi = gen_rtx_HIGH (Pmode, copy_rtx (x));
x = gen_rtx_LO_SUM (Pmode, hi, x);
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
opnum, (enum reload_type) type); opnum, (enum reload_type) type);
...@@ -6267,7 +6293,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, ...@@ -6267,7 +6293,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
opnum, (enum reload_type)type); opnum, (enum reload_type) type);
*win = 1; *win = 1;
return x; return x;
} }
...@@ -6308,7 +6334,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, ...@@ -6308,7 +6334,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
opnum, (enum reload_type)type); opnum, (enum reload_type) type);
*win = 1; *win = 1;
return x; return x;
} }
...@@ -6335,8 +6361,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, ...@@ -6335,8 +6361,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
if (TARGET_TOC if (TARGET_TOC
&& reg_offset_p && reg_offset_p
&& GET_CODE (x) == SYMBOL_REF && GET_CODE (x) == SYMBOL_REF
&& constant_pool_expr_p (x) && use_toc_relative_ref (x))
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
{ {
x = create_TOC_reference (x, NULL_RTX); x = create_TOC_reference (x, NULL_RTX);
if (TARGET_CMODEL != CMODEL_SMALL) if (TARGET_CMODEL != CMODEL_SMALL)
...@@ -6571,9 +6596,13 @@ rs6000_debug_mode_dependent_address (const_rtx addr) ...@@ -6571,9 +6596,13 @@ rs6000_debug_mode_dependent_address (const_rtx addr)
rtx rtx
rs6000_find_base_term (rtx op) rs6000_find_base_term (rtx op)
{ {
rtx base, offset; rtx base;
split_const (op, &base, &offset); base = op;
if (GET_CODE (base) == CONST)
base = XEXP (base, 0);
if (GET_CODE (base) == PLUS)
base = XEXP (base, 0);
if (GET_CODE (base) == UNSPEC) if (GET_CODE (base) == UNSPEC)
switch (XINT (base, 1)) switch (XINT (base, 1))
{ {
...@@ -7225,33 +7254,13 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) ...@@ -7225,33 +7254,13 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
/* If this is a SYMBOL_REF that refers to a constant pool entry, /* 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 and we have put it in the TOC, we just need to make a TOC-relative
reference to it. */ reference to it. */
if ((TARGET_TOC 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 && GET_CODE (operands[1]) == SYMBOL_REF
&& !CONSTANT_POOL_ADDRESS_P (operands[1]) && use_toc_relative_ref (operands[1]))
&& SYMBOL_REF_LOCAL_P (operands[1]))) operands[1] = create_TOC_reference (operands[1], operands[0]);
{
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 else if (mode == Pmode
&& CONSTANT_P (operands[1]) && CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != HIGH && GET_CODE (operands[1]) != HIGH
&& !(TARGET_CMODEL != CMODEL_SMALL
&& GET_CODE (operands[1]) == CONST
&& GET_CODE (XEXP (operands[1], 0)) == PLUS
&& GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == HIGH)
&& ((GET_CODE (operands[1]) != CONST_INT && ((GET_CODE (operands[1]) != CONST_INT
&& ! easy_fp_constant (operands[1], mode)) && ! easy_fp_constant (operands[1], mode))
|| (GET_CODE (operands[1]) == CONST_INT || (GET_CODE (operands[1]) == CONST_INT
...@@ -7259,9 +7268,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) ...@@ -7259,9 +7268,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
> (TARGET_CMODEL != CMODEL_SMALL ? 3 : 2))) > (TARGET_CMODEL != CMODEL_SMALL ? 3 : 2)))
|| (GET_CODE (operands[0]) == REG || (GET_CODE (operands[0]) == REG
&& FP_REGNO_P (REGNO (operands[0])))) && FP_REGNO_P (REGNO (operands[0]))))
&& ! legitimate_constant_pool_address_p (operands[1], mode, && !toc_relative_expr_p (operands[1], false)
false)
&& ! toc_relative_expr_p (operands[1])
&& (TARGET_CMODEL == CMODEL_SMALL && (TARGET_CMODEL == CMODEL_SMALL
|| can_create_pseudo_p () || can_create_pseudo_p ()
|| (REG_P (operands[0]) || (REG_P (operands[0])
...@@ -7311,16 +7318,8 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) ...@@ -7311,16 +7318,8 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
get_pool_constant (XEXP (operands[1], 0)), get_pool_constant (XEXP (operands[1], 0)),
get_pool_mode (XEXP (operands[1], 0)))) get_pool_mode (XEXP (operands[1], 0))))
{ {
rtx tocref; rtx tocref = create_TOC_reference (XEXP (operands[1], 0),
rtx reg = NULL_RTX; operands[0]);
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); operands[1] = gen_const_mem (mode, tocref);
set_mem_alias_set (operands[1], get_TOC_alias_set ()); set_mem_alias_set (operands[1], get_TOC_alias_set ());
} }
...@@ -14730,7 +14729,7 @@ print_operand (FILE *file, rtx x, int code) ...@@ -14730,7 +14729,7 @@ print_operand (FILE *file, rtx x, int code)
case 'D': case 'D':
/* Like 'J' but get to the GT bit only. */ /* Like 'J' but get to the GT bit only. */
gcc_assert (GET_CODE (x) == REG); gcc_assert (REG_P (x));
/* Bit 1 is GT bit. */ /* Bit 1 is GT bit. */
i = 4 * (REGNO (x) - CR0_REGNO) + 1; i = 4 * (REGNO (x) - CR0_REGNO) + 1;
...@@ -14850,9 +14849,9 @@ print_operand (FILE *file, rtx x, int code) ...@@ -14850,9 +14849,9 @@ print_operand (FILE *file, rtx x, int code)
case 'L': case 'L':
/* Write second word of DImode or DFmode reference. Works on register /* Write second word of DImode or DFmode reference. Works on register
or non-indexed memory only. */ or non-indexed memory only. */
if (GET_CODE (x) == REG) if (REG_P (x))
fputs (reg_names[REGNO (x) + 1], file); fputs (reg_names[REGNO (x) + 1], file);
else if (GET_CODE (x) == MEM) else if (MEM_P (x))
{ {
/* Handle possible auto-increment. Since it is pre-increment and /* Handle possible auto-increment. Since it is pre-increment and
we have already done it, we can just use an offset of word. */ we have already done it, we can just use an offset of word. */
...@@ -15021,7 +15020,7 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15021,7 +15020,7 @@ print_operand (FILE *file, rtx x, int code)
case 't': case 't':
/* Like 'J' but get to the OVERFLOW/UNORDERED bit. */ /* Like 'J' but get to the OVERFLOW/UNORDERED bit. */
gcc_assert (GET_CODE (x) == REG && GET_MODE (x) == CCmode); gcc_assert (REG_P (x) && GET_MODE (x) == CCmode);
/* Bit 3 is OV bit. */ /* Bit 3 is OV bit. */
i = 4 * (REGNO (x) - CR0_REGNO) + 3; i = 4 * (REGNO (x) - CR0_REGNO) + 3;
...@@ -15061,7 +15060,7 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15061,7 +15060,7 @@ print_operand (FILE *file, rtx x, int code)
case 'U': case 'U':
/* Print `u' if this has an auto-increment or auto-decrement. */ /* Print `u' if this has an auto-increment or auto-decrement. */
if (GET_CODE (x) == MEM if (MEM_P (x)
&& (GET_CODE (XEXP (x, 0)) == PRE_INC && (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC || GET_CODE (XEXP (x, 0)) == PRE_DEC
|| GET_CODE (XEXP (x, 0)) == PRE_MODIFY)) || GET_CODE (XEXP (x, 0)) == PRE_MODIFY))
...@@ -15153,7 +15152,7 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15153,7 +15152,7 @@ print_operand (FILE *file, rtx x, int code)
return; return;
case 'X': case 'X':
if (GET_CODE (x) == MEM if (MEM_P (x)
&& (legitimate_indexed_address_p (XEXP (x, 0), 0) && (legitimate_indexed_address_p (XEXP (x, 0), 0)
|| (GET_CODE (XEXP (x, 0)) == PRE_MODIFY || (GET_CODE (XEXP (x, 0)) == PRE_MODIFY
&& legitimate_indexed_address_p (XEXP (XEXP (x, 0), 1), 0)))) && legitimate_indexed_address_p (XEXP (XEXP (x, 0), 1), 0))))
...@@ -15162,9 +15161,9 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15162,9 +15161,9 @@ print_operand (FILE *file, rtx x, int code)
case 'Y': case 'Y':
/* Like 'L', for third word of TImode */ /* Like 'L', for third word of TImode */
if (GET_CODE (x) == REG) if (REG_P (x))
fputs (reg_names[REGNO (x) + 2], file); fputs (reg_names[REGNO (x) + 2], file);
else if (GET_CODE (x) == MEM) else if (MEM_P (x))
{ {
if (GET_CODE (XEXP (x, 0)) == PRE_INC if (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC) || GET_CODE (XEXP (x, 0)) == PRE_DEC)
...@@ -15212,9 +15211,9 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15212,9 +15211,9 @@ print_operand (FILE *file, rtx x, int code)
case 'Z': case 'Z':
/* Like 'L', for last word of TImode. */ /* Like 'L', for last word of TImode. */
if (GET_CODE (x) == REG) if (REG_P (x))
fputs (reg_names[REGNO (x) + 3], file); fputs (reg_names[REGNO (x) + 3], file);
else if (GET_CODE (x) == MEM) else if (MEM_P (x))
{ {
if (GET_CODE (XEXP (x, 0)) == PRE_INC if (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC) || GET_CODE (XEXP (x, 0)) == PRE_DEC)
...@@ -15234,7 +15233,7 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15234,7 +15233,7 @@ print_operand (FILE *file, rtx x, int code)
{ {
rtx tmp; rtx tmp;
gcc_assert (GET_CODE (x) == MEM); gcc_assert (MEM_P (x));
tmp = XEXP (x, 0); tmp = XEXP (x, 0);
...@@ -15245,7 +15244,7 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15245,7 +15244,7 @@ print_operand (FILE *file, rtx x, int code)
|| GET_MODE (x) == TImode)) || GET_MODE (x) == TImode))
{ {
/* Handle [reg]. */ /* Handle [reg]. */
if (GET_CODE (tmp) == REG) if (REG_P (tmp))
{ {
fprintf (file, "0(%s)", reg_names[REGNO (tmp)]); fprintf (file, "0(%s)", reg_names[REGNO (tmp)]);
break; break;
...@@ -15256,7 +15255,7 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15256,7 +15255,7 @@ print_operand (FILE *file, rtx x, int code)
{ {
int x; int x;
gcc_assert (GET_CODE (XEXP (tmp, 0)) == REG); gcc_assert (REG_P (XEXP (tmp, 0)));
x = INTVAL (XEXP (tmp, 1)); x = INTVAL (XEXP (tmp, 1));
fprintf (file, "%d(%s)", x, reg_names[REGNO (XEXP (tmp, 0))]); fprintf (file, "%d(%s)", x, reg_names[REGNO (XEXP (tmp, 0))]);
...@@ -15273,7 +15272,7 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15273,7 +15272,7 @@ print_operand (FILE *file, rtx x, int code)
else if (VECTOR_MEM_VSX_P (GET_MODE (x)) else if (VECTOR_MEM_VSX_P (GET_MODE (x))
&& GET_CODE (tmp) == PRE_MODIFY) && GET_CODE (tmp) == PRE_MODIFY)
tmp = XEXP (tmp, 1); tmp = XEXP (tmp, 1);
if (GET_CODE (tmp) == REG) if (REG_P (tmp))
fprintf (file, "0,%s", reg_names[REGNO (tmp)]); fprintf (file, "0,%s", reg_names[REGNO (tmp)]);
else else
{ {
...@@ -15296,9 +15295,9 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15296,9 +15295,9 @@ print_operand (FILE *file, rtx x, int code)
} }
case 0: case 0:
if (GET_CODE (x) == REG) if (REG_P (x))
fprintf (file, "%s", reg_names[REGNO (x)]); fprintf (file, "%s", reg_names[REGNO (x)]);
else if (GET_CODE (x) == MEM) else if (MEM_P (x))
{ {
/* We need to handle PRE_INC and PRE_DEC here, since we need to /* We need to handle PRE_INC and PRE_DEC here, since we need to
know the width from the mode. */ know the width from the mode. */
...@@ -15315,14 +15314,14 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15315,14 +15314,14 @@ print_operand (FILE *file, rtx x, int code)
} }
else else
{ {
if (toc_relative_expr_p (x)) if (toc_relative_expr_p (x, false))
/* This hack along with a corresponding hack in /* This hack along with a corresponding hack in
rs6000_output_addr_const_extra arranges to output addends rs6000_output_addr_const_extra arranges to output addends
where the assembler expects to find them. eg. where the assembler expects to find them. eg.
(const (plus (unspec [symbol_ref ("x") tocrel]) 4)) (plus (unspec [(symbol_ref ("x")) (reg 2)] tocrel) 4)
without this hack would be output as "x@toc+4". We without this hack would be output as "x@toc+4". We
want "x+4@toc". */ want "x+4@toc". */
output_addr_const (file, tocrel_base); output_addr_const (file, CONST_CAST_RTX (tocrel_base));
else else
output_addr_const (file, x); output_addr_const (file, x);
} }
...@@ -15342,7 +15341,7 @@ print_operand (FILE *file, rtx x, int code) ...@@ -15342,7 +15341,7 @@ print_operand (FILE *file, rtx x, int code)
void void
print_operand_address (FILE *file, rtx x) print_operand_address (FILE *file, rtx x)
{ {
if (GET_CODE (x) == REG) if (REG_P (x))
fprintf (file, "0(%s)", reg_names[ REGNO (x) ]); fprintf (file, "0(%s)", reg_names[ REGNO (x) ]);
else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST
|| GET_CODE (x) == LABEL_REF) || GET_CODE (x) == LABEL_REF)
...@@ -15354,9 +15353,9 @@ print_operand_address (FILE *file, rtx x) ...@@ -15354,9 +15353,9 @@ print_operand_address (FILE *file, rtx x)
else else
gcc_assert (!TARGET_TOC); gcc_assert (!TARGET_TOC);
} }
else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG) else if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0))
&& REG_P (XEXP (x, 1)))
{ {
gcc_assert (REG_P (XEXP (x, 0)));
if (REGNO (XEXP (x, 0)) == 0) if (REGNO (XEXP (x, 0)) == 0)
fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ], fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ],
reg_names[ REGNO (XEXP (x, 0)) ]); reg_names[ REGNO (XEXP (x, 0)) ]);
...@@ -15364,11 +15363,12 @@ print_operand_address (FILE *file, rtx x) ...@@ -15364,11 +15363,12 @@ print_operand_address (FILE *file, rtx x)
fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 0)) ], fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 0)) ],
reg_names[ REGNO (XEXP (x, 1)) ]); reg_names[ REGNO (XEXP (x, 1)) ]);
} }
else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT) else if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0))
&& GET_CODE (XEXP (x, 1)) == CONST_INT)
fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%s)", fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%s)",
INTVAL (XEXP (x, 1)), reg_names[ REGNO (XEXP (x, 0)) ]); INTVAL (XEXP (x, 1)), reg_names[ REGNO (XEXP (x, 0)) ]);
#if TARGET_MACHO #if TARGET_MACHO
else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG else if (GET_CODE (x) == LO_SUM && REG_P (XEXP (x, 0))
&& CONSTANT_P (XEXP (x, 1))) && CONSTANT_P (XEXP (x, 1)))
{ {
fprintf (file, "lo16("); fprintf (file, "lo16(");
...@@ -15376,29 +15376,29 @@ print_operand_address (FILE *file, rtx x) ...@@ -15376,29 +15376,29 @@ print_operand_address (FILE *file, rtx x)
fprintf (file, ")(%s)", reg_names[ REGNO (XEXP (x, 0)) ]); fprintf (file, ")(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
} }
#endif #endif
else if (legitimate_constant_pool_address_p (x, QImode, true)) #if TARGET_ELF
else if (GET_CODE (x) == LO_SUM && REG_P (XEXP (x, 0))
&& CONSTANT_P (XEXP (x, 1)))
{
output_addr_const (file, XEXP (x, 1));
fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
}
#endif
else if (toc_relative_expr_p (x, false))
{ {
/* This hack along with a corresponding hack in /* This hack along with a corresponding hack in
rs6000_output_addr_const_extra arranges to output addends rs6000_output_addr_const_extra arranges to output addends
where the assembler expects to find them. eg. where the assembler expects to find them. eg.
(lo_sum (reg 9) (lo_sum (reg 9)
. (const (plus (unspec [symbol_ref ("x") tocrel]) 8))) . (plus (unspec [(symbol_ref ("x")) (reg 2)] tocrel) 8))
without this hack would be output as "x@toc+8@l(9)". We without this hack would be output as "x@toc+8@l(9)". We
want "x+8@toc@l(9)". */ want "x+8@toc@l(9)". */
output_addr_const (file, tocrel_base); output_addr_const (file, CONST_CAST_RTX (tocrel_base));
if (GET_CODE (x) == LO_SUM) if (GET_CODE (x) == LO_SUM)
fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]); fprintf (file, "@l(%s)", reg_names[REGNO (XEXP (x, 0))]);
else else
fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]); fprintf (file, "(%s)", reg_names[REGNO (XVECEXP (tocrel_base, 0, 1))]);
} }
#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
else else
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -15412,13 +15412,15 @@ rs6000_output_addr_const_extra (FILE *file, rtx x) ...@@ -15412,13 +15412,15 @@ rs6000_output_addr_const_extra (FILE *file, rtx x)
switch (XINT (x, 1)) switch (XINT (x, 1))
{ {
case UNSPEC_TOCREL: case UNSPEC_TOCREL:
gcc_assert (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF); gcc_checking_assert (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF
&& REG_P (XVECEXP (x, 0, 1))
&& REGNO (XVECEXP (x, 0, 1)) == TOC_REGISTER);
output_addr_const (file, XVECEXP (x, 0, 0)); output_addr_const (file, XVECEXP (x, 0, 0));
if (x == tocrel_base && tocrel_offset != const0_rtx) if (x == tocrel_base && tocrel_offset != const0_rtx)
{ {
if (INTVAL (tocrel_offset) >= 0) if (INTVAL (tocrel_offset) >= 0)
fprintf (file, "+"); fprintf (file, "+");
output_addr_const (file, tocrel_offset); output_addr_const (file, CONST_CAST_RTX (tocrel_offset));
} }
if (!TARGET_AIX || (TARGET_ELF && TARGET_MINIMAL_TOC)) if (!TARGET_AIX || (TARGET_ELF && TARGET_MINIMAL_TOC))
{ {
...@@ -18501,7 +18503,7 @@ uses_TOC (void) ...@@ -18501,7 +18503,7 @@ uses_TOC (void)
rtx rtx
create_TOC_reference (rtx symbol, rtx largetoc_reg) create_TOC_reference (rtx symbol, rtx largetoc_reg)
{ {
rtx tocrel, tocreg; rtx tocrel, tocreg, hi;
if (TARGET_DEBUG_ADDR) if (TARGET_DEBUG_ADDR)
{ {
...@@ -18519,24 +18521,18 @@ create_TOC_reference (rtx symbol, rtx largetoc_reg) ...@@ -18519,24 +18521,18 @@ create_TOC_reference (rtx symbol, rtx largetoc_reg)
if (!can_create_pseudo_p ()) if (!can_create_pseudo_p ())
df_set_regs_ever_live (TOC_REGISTER, true); df_set_regs_ever_live (TOC_REGISTER, true);
tocrel = gen_rtx_CONST (Pmode,
gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol),
UNSPEC_TOCREL));
tocreg = gen_rtx_REG (Pmode, TOC_REGISTER); tocreg = gen_rtx_REG (Pmode, TOC_REGISTER);
if (TARGET_CMODEL != CMODEL_SMALL) tocrel = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, symbol, tocreg), UNSPEC_TOCREL);
{ if (TARGET_CMODEL == CMODEL_SMALL || can_create_pseudo_p ())
rtx hi = gen_rtx_CONST (Pmode, return tocrel;
gen_rtx_PLUS (Pmode, tocreg,
gen_rtx_HIGH (Pmode, tocrel))); hi = gen_rtx_HIGH (Pmode, copy_rtx (tocrel));
if (largetoc_reg != NULL) if (largetoc_reg != NULL)
{ {
emit_move_insn (largetoc_reg, hi); emit_move_insn (largetoc_reg, hi);
hi = largetoc_reg; hi = largetoc_reg;
} }
return gen_rtx_LO_SUM (Pmode, hi, copy_rtx (tocrel)); return gen_rtx_LO_SUM (Pmode, hi, tocrel);
}
else
return gen_rtx_PLUS (Pmode, tocreg, tocrel);
} }
/* Issue assembly directives that create a reference to the given DWARF /* Issue assembly directives that create a reference to the given DWARF
......
;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler ;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler
;; Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, ;; Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 ;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
;; 2011, 2012
;; Free Software Foundation, Inc. ;; Free Software Foundation, Inc.
;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) ;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
...@@ -9305,8 +9306,8 @@ ...@@ -9305,8 +9306,8 @@
(set_attr "length" "4")]) (set_attr "length" "4")])
(define_insn "*movsi_internal1" (define_insn "*movsi_internal1"
[(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h") [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,*q,*c*l,*h,*h")
(match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0"))] (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,*h,r,r,r,0"))]
"!TARGET_SINGLE_FPU && "!TARGET_SINGLE_FPU &&
(gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))" (gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))"
"@ "@
...@@ -9317,18 +9318,17 @@ ...@@ -9317,18 +9318,17 @@
{lil|li} %0,%1 {lil|li} %0,%1
{liu|lis} %0,%v1 {liu|lis} %0,%v1
# #
{cal|la} %0,%a1
mf%1 %0 mf%1 %0
mt%0 %1 mt%0 %1
mt%0 %1 mt%0 %1
mt%0 %1 mt%0 %1
{cror 0,0,0|nop}" {cror 0,0,0|nop}"
[(set_attr "type" "*,*,load,store,*,*,*,*,mfjmpr,*,mtjmpr,*,*") [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,*,mtjmpr,*,*")
(set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")]) (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4")])
(define_insn "*movsi_internal1_single" (define_insn "*movsi_internal1_single"
[(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h,m,*f") [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,*q,*c*l,*h,*h,m,*f")
(match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0,f,m"))] (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,*h,r,r,r,0,f,m"))]
"TARGET_SINGLE_FPU && "TARGET_SINGLE_FPU &&
(gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))" (gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))"
"@ "@
...@@ -9339,7 +9339,6 @@ ...@@ -9339,7 +9339,6 @@
{lil|li} %0,%1 {lil|li} %0,%1
{liu|lis} %0,%v1 {liu|lis} %0,%v1
# #
{cal|la} %0,%a1
mf%1 %0 mf%1 %0
mt%0 %1 mt%0 %1
mt%0 %1 mt%0 %1
...@@ -9347,8 +9346,8 @@ ...@@ -9347,8 +9346,8 @@
{cror 0,0,0|nop} {cror 0,0,0|nop}
stfs%U0%X0 %1, %0 stfs%U0%X0 %1, %0
lfs%U1%X1 %0, %1" lfs%U1%X1 %0, %1"
[(set_attr "type" "*,*,load,store,*,*,*,*,mfjmpr,*,mtjmpr,*,*,*,*") [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,*,mtjmpr,*,*,*,*")
(set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4,4,4")]) (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4,4")])
;; Split a load of a large constant into the appropriate two-insn ;; Split a load of a large constant into the appropriate two-insn
;; sequence. ;; sequence.
...@@ -9543,8 +9542,8 @@ ...@@ -9543,8 +9542,8 @@
(set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,8")]) (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,8")])
(define_insn "*movsf_softfloat" (define_insn "*movsf_softfloat"
[(set (match_operand:SF 0 "nonimmediate_operand" "=r,cl,q,r,r,m,r,r,r,r,r,*h") [(set (match_operand:SF 0 "nonimmediate_operand" "=r,cl,q,r,r,m,r,r,r,r,*h")
(match_operand:SF 1 "input_operand" "r,r,r,h,m,r,I,L,R,G,Fn,0"))] (match_operand:SF 1 "input_operand" "r,r,r,h,m,r,I,L,G,Fn,0"))]
"(gpc_reg_operand (operands[0], SFmode) "(gpc_reg_operand (operands[0], SFmode)
|| gpc_reg_operand (operands[1], SFmode)) || gpc_reg_operand (operands[1], SFmode))
&& (TARGET_SOFT_FLOAT || !TARGET_FPRS)" && (TARGET_SOFT_FLOAT || !TARGET_FPRS)"
...@@ -9557,12 +9556,11 @@ ...@@ -9557,12 +9556,11 @@
{st%U0%X0|stw%U0%X0} %1,%0 {st%U0%X0|stw%U0%X0} %1,%0
{lil|li} %0,%1 {lil|li} %0,%1
{liu|lis} %0,%v1 {liu|lis} %0,%v1
{cal|la} %0,%a1
# #
# #
{cror 0,0,0|nop}" {cror 0,0,0|nop}"
[(set_attr "type" "*,mtjmpr,*,mfjmpr,load,store,*,*,*,*,*,*") [(set_attr "type" "*,mtjmpr,*,mfjmpr,load,store,*,*,*,*,*")
(set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,4")]) (set_attr "length" "4,4,4,4,4,4,4,4,4,8,4")])
(define_expand "movdf" (define_expand "movdf"
...@@ -10190,8 +10188,8 @@ ...@@ -10190,8 +10188,8 @@
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }) { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_insn "*movdi_mfpgpr" (define_insn "*movdi_mfpgpr"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*d,*d,m,r,*h,*h,r,*d") [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,*d,*d,m,r,*h,*h,r,*d")
(match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,d,m,d,*h,r,0,*d,r"))] (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,d,m,d,*h,r,0,*d,r"))]
"TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS
&& (gpc_reg_operand (operands[0], DImode) && (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))" || gpc_reg_operand (operands[1], DImode))"
...@@ -10202,7 +10200,6 @@ ...@@ -10202,7 +10200,6 @@
li %0,%1 li %0,%1
lis %0,%v1 lis %0,%v1
# #
la %0,%a1
fmr %0,%1 fmr %0,%1
lfd%U1%X1 %0,%1 lfd%U1%X1 %0,%1
stfd%U0%X0 %1,%0 stfd%U0%X0 %1,%0
...@@ -10211,12 +10208,12 @@ ...@@ -10211,12 +10208,12 @@
{cror 0,0,0|nop} {cror 0,0,0|nop}
mftgpr %0,%1 mftgpr %0,%1
mffgpr %0,%1" mffgpr %0,%1"
[(set_attr "type" "*,load,store,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,mftgpr,mffgpr") [(set_attr "type" "*,load,store,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,mftgpr,mffgpr")
(set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4")]) (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4")])
(define_insn "*movdi_internal64" (define_insn "*movdi_internal64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*d,*d,m,r,*h,*h,?wa") [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,*d,*d,m,r,*h,*h,?wa")
(match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,d,m,d,*h,r,0,O"))] (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,d,m,d,*h,r,0,O"))]
"TARGET_POWERPC64 && (!TARGET_MFPGPR || !TARGET_HARD_FLOAT || !TARGET_FPRS) "TARGET_POWERPC64 && (!TARGET_MFPGPR || !TARGET_HARD_FLOAT || !TARGET_FPRS)
&& (gpc_reg_operand (operands[0], DImode) && (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))" || gpc_reg_operand (operands[1], DImode))"
...@@ -10227,7 +10224,6 @@ ...@@ -10227,7 +10224,6 @@
li %0,%1 li %0,%1
lis %0,%v1 lis %0,%v1
# #
la %0,%a1
fmr %0,%1 fmr %0,%1
lfd%U1%X1 %0,%1 lfd%U1%X1 %0,%1
stfd%U0%X0 %1,%0 stfd%U0%X0 %1,%0
...@@ -10235,8 +10231,8 @@ ...@@ -10235,8 +10231,8 @@
mt%0 %1 mt%0 %1
{cror 0,0,0|nop} {cror 0,0,0|nop}
xxlxor %x0,%x0,%x0" xxlxor %x0,%x0,%x0"
[(set_attr "type" "*,load,store,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,vecsimple") [(set_attr "type" "*,load,store,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,vecsimple")
(set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4")]) (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4")])
;; immediate value valid for a single instruction hiding in a const_double ;; immediate value valid for a single instruction hiding in a const_double
(define_insn "" (define_insn ""
...@@ -11592,10 +11588,8 @@ ...@@ -11592,10 +11588,8 @@
"addi %0,%1,%2@got@tlsgd" "addi %0,%1,%2@got@tlsgd"
"&& TARGET_CMODEL != CMODEL_SMALL" "&& TARGET_CMODEL != CMODEL_SMALL"
[(set (match_dup 3) [(set (match_dup 3)
(const:TLSmode
(plus:TLSmode (match_dup 1)
(high:TLSmode (high:TLSmode
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD))))) (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGD)))
(set (match_dup 0) (set (match_dup 0)
(lo_sum:TLSmode (match_dup 3) (lo_sum:TLSmode (match_dup 3)
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)))] (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)))]
...@@ -11610,11 +11604,10 @@ ...@@ -11610,11 +11604,10 @@
(define_insn "*tls_gd_high<TLSmode:tls_abi_suffix>" (define_insn "*tls_gd_high<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
(const:TLSmode
(plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
(high:TLSmode (high:TLSmode
(unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
UNSPEC_TLSGD)))))] (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL" "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
"addis %0,%1,%2@got@tlsgd@ha" "addis %0,%1,%2@got@tlsgd@ha"
[(set_attr "length" "4")]) [(set_attr "length" "4")])
...@@ -11729,10 +11722,8 @@ ...@@ -11729,10 +11722,8 @@
"addi %0,%1,%&@got@tlsld" "addi %0,%1,%&@got@tlsld"
"&& TARGET_CMODEL != CMODEL_SMALL" "&& TARGET_CMODEL != CMODEL_SMALL"
[(set (match_dup 2) [(set (match_dup 2)
(const:TLSmode
(plus:TLSmode (match_dup 1)
(high:TLSmode (high:TLSmode
(unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD))))) (unspec:TLSmode [(const_int 0) (match_dup 1)] UNSPEC_TLSLD)))
(set (match_dup 0) (set (match_dup 0)
(lo_sum:TLSmode (match_dup 2) (lo_sum:TLSmode (match_dup 2)
(unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))] (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))]
...@@ -11747,10 +11738,10 @@ ...@@ -11747,10 +11738,10 @@
(define_insn "*tls_ld_high<TLSmode:tls_abi_suffix>" (define_insn "*tls_ld_high<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
(const:TLSmode
(plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
(high:TLSmode (high:TLSmode
(unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))))] (unspec:TLSmode [(const_int 0)
(match_operand:TLSmode 1 "gpc_reg_operand" "b")]
UNSPEC_TLSLD)))]
"HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL" "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL"
"addis %0,%1,%&@got@tlsld@ha" "addis %0,%1,%&@got@tlsld@ha"
[(set_attr "length" "4")]) [(set_attr "length" "4")])
...@@ -11826,10 +11817,8 @@ ...@@ -11826,10 +11817,8 @@
"l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel(%1)" "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel(%1)"
"&& TARGET_CMODEL != CMODEL_SMALL" "&& TARGET_CMODEL != CMODEL_SMALL"
[(set (match_dup 3) [(set (match_dup 3)
(const:TLSmode
(plus:TLSmode (match_dup 1)
(high:TLSmode (high:TLSmode
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL))))) (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTDTPREL)))
(set (match_dup 0) (set (match_dup 0)
(lo_sum:TLSmode (match_dup 3) (lo_sum:TLSmode (match_dup 3)
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL)))] (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL)))]
...@@ -11844,11 +11833,10 @@ ...@@ -11844,11 +11833,10 @@
(define_insn "*tls_got_dtprel_high<TLSmode:tls_abi_suffix>" (define_insn "*tls_got_dtprel_high<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
(const:TLSmode
(plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
(high:TLSmode (high:TLSmode
(unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
UNSPEC_TLSGOTDTPREL)))))] (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTDTPREL)))]
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL" "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
"addis %0,%1,%2@got@dtprel@ha" "addis %0,%1,%2@got@dtprel@ha"
[(set_attr "length" "4")]) [(set_attr "length" "4")])
...@@ -11898,10 +11886,8 @@ ...@@ -11898,10 +11886,8 @@
"l<TLSmode:tls_insn_suffix> %0,%2@got@tprel(%1)" "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel(%1)"
"&& TARGET_CMODEL != CMODEL_SMALL" "&& TARGET_CMODEL != CMODEL_SMALL"
[(set (match_dup 3) [(set (match_dup 3)
(const:TLSmode
(plus:TLSmode (match_dup 1)
(high:TLSmode (high:TLSmode
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL))))) (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTTPREL)))
(set (match_dup 0) (set (match_dup 0)
(lo_sum:TLSmode (match_dup 3) (lo_sum:TLSmode (match_dup 3)
(unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL)))] (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL)))]
...@@ -11916,11 +11902,10 @@ ...@@ -11916,11 +11902,10 @@
(define_insn "*tls_got_tprel_high<TLSmode:tls_abi_suffix>" (define_insn "*tls_got_tprel_high<TLSmode:tls_abi_suffix>"
[(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b")
(const:TLSmode
(plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b")
(high:TLSmode (high:TLSmode
(unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b")
UNSPEC_TLSGOTTPREL)))))] (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTTPREL)))]
"HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL" "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
"addis %0,%1,%2@got@tprel@ha" "addis %0,%1,%2@got@tprel@ha"
[(set_attr "length" "4")]) [(set_attr "length" "4")])
...@@ -12277,6 +12262,45 @@ ...@@ -12277,6 +12262,45 @@
DONE; DONE;
}") }")
;; Largetoc support
(define_insn "*largetoc_high"
[(set (match_operand:DI 0 "gpc_reg_operand" "=b*r")
(high:DI
(unspec [(match_operand:DI 1 "" "")
(match_operand:DI 2 "gpc_reg_operand" "b")]
UNSPEC_TOCREL)))]
"TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
"{cau|addis} %0,%2,%1@toc@ha")
(define_insn "*largetoc_high_plus"
[(set (match_operand:DI 0 "gpc_reg_operand" "=b*r")
(high:DI
(plus:DI
(unspec [(match_operand:DI 1 "" "")
(match_operand:DI 2 "gpc_reg_operand" "b")]
UNSPEC_TOCREL)
(match_operand 3 "const_int_operand" "n"))))]
"TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
"{cau|addis} %0,%2,%1+%3@toc@ha")
(define_insn "*largetoc_low"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,!*r")
(match_operand:DI 2 "" "")))]
"TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
"@
{cal %0,%2@l(%1)|addi %0,%1,%2@l}
{ai|addic} %0,%1,%2@l")
(define_insn_and_split "*tocref<mode>"
[(set (match_operand:P 0 "gpc_reg_operand" "=b*r")
(match_operand:P 1 "small_toc_ref" "R"))]
"TARGET_TOC"
"{cal|la} %0,%a1"
"&& TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL && reload_completed"
[(set (match_dup 0) (high:P (match_dup 1)))
(set (match_dup 0) (lo_sum:P (match_dup 0) (match_dup 1)))])
;; Elf specific ways of loading addresses for non-PIC code. ;; Elf specific ways of loading addresses for non-PIC code.
;; The output of this could be r0, but we make a very strong ;; The output of this could be r0, but we make a very strong
;; preference for a base register because it will usually ;; preference for a base register because it will usually
...@@ -12296,22 +12320,6 @@ ...@@ -12296,22 +12320,6 @@
{cal|la} %0,%2@l(%1) {cal|la} %0,%2@l(%1)
{ai|addic} %0,%1,%K2") {ai|addic} %0,%1,%K2")
;; Largetoc support
(define_insn "largetoc_high"
[(set (match_operand:DI 0 "gpc_reg_operand" "=b")
(const:DI
(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}")
;; Call and call_value insns ;; Call and call_value insns
(define_expand "call" (define_expand "call"
[(parallel [(call (mem:SI (match_operand 0 "address_operand" "")) [(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment