summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-11 06:07:51 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-11 06:07:51 +0000
commit7f343dad554f0166f664cba7d6ab809ee4473f13 (patch)
tree5f549f9387f37ae57d7747549dd4403b83905370 /gcc/config
parentefdfa4676cd3506381bd987f7365767bb05c934a (diff)
downloadgcc-7f343dad554f0166f664cba7d6ab809ee4473f13.tar.gz
2016-02-11 Basile Starynkevitch <basile@starynkevitch.net>
{{merging with even more of GCC 6, using subversion 1.9 svn merge -r227821:227910 ^/trunk }} git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@233315 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/aarch64/aarch64.md46
-rw-r--r--gcc/config/arm/arm-protos.h1
-rw-r--r--gcc/config/arm/arm.c536
-rw-r--r--gcc/config/arm/arm.md26
-rw-r--r--gcc/config/arm/linux-elf.h3
-rw-r--r--gcc/config/arm/unspecs.md2
-rw-r--r--gcc/config/ft32/ft32.c8
-rw-r--r--gcc/config/i386/i386-interix.h5
-rw-r--r--gcc/config/rs6000/aix61.h2
-rw-r--r--gcc/config/rs6000/rs6000-protos.h4
-rw-r--r--gcc/config/rs6000/rs6000.c26
-rw-r--r--gcc/config/sh/sh.c2
-rw-r--r--gcc/config/sh/sh.md8
-rw-r--r--gcc/config/sparc/sparc-protos.h2
-rw-r--r--gcc/config/sparc/sparc.c20
-rw-r--r--gcc/config/sparc/sparc.h14
-rw-r--r--gcc/config/sparc/sparc.md32
-rw-r--r--gcc/config/spu/spu-elf.h2
18 files changed, 587 insertions, 152 deletions
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 88ba72e3ac7..925c6b1d377 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -4412,6 +4412,52 @@
[(set_attr "type" "f_minmax<s>")]
)
+;; For copysign (x, y), we want to generate:
+;;
+;; LDR d2, #(1 << 63)
+;; BSL v2.8b, [y], [x]
+;;
+;; or another, equivalent, sequence using one of BSL/BIT/BIF.
+;; aarch64_simd_bsldf will select the best suited of these instructions
+;; to generate based on register allocation, and knows how to partially
+;; constant fold based on the values of X and Y, so expand through that.
+
+(define_expand "copysigndf3"
+ [(match_operand:DF 0 "register_operand")
+ (match_operand:DF 1 "register_operand")
+ (match_operand:DF 2 "register_operand")]
+ "TARGET_FLOAT && TARGET_SIMD"
+{
+ rtx mask = gen_reg_rtx (DImode);
+ emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63));
+ emit_insn (gen_aarch64_simd_bsldf (operands[0], mask,
+ operands[2], operands[1]));
+ DONE;
+}
+)
+
+;; As above, but we must first get to a 64-bit value if we wish to use
+;; aarch64_simd_bslv2sf.
+
+(define_expand "copysignsf3"
+ [(match_operand:SF 0 "register_operand")
+ (match_operand:SF 1 "register_operand")
+ (match_operand:SF 2 "register_operand")]
+ "TARGET_FLOAT && TARGET_SIMD"
+{
+ rtx mask = gen_reg_rtx (DImode);
+
+ /* Juggle modes to get us in to a vector mode for BSL. */
+ rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode);
+ rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode);
+ rtx tmp = gen_reg_rtx (V2SFmode);
+ emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31));
+ emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1));
+ emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode));
+ DONE;
+}
+)
+
;; -------------------------------------------------------------------
;; Reload support
;; -------------------------------------------------------------------
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index d3d7216488e..f9b12764b09 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -146,6 +146,7 @@ extern const char *output_add_immediate (rtx *);
extern const char *arithmetic_instr (rtx, int);
extern void output_ascii_pseudo_op (FILE *, const unsigned char *, int);
extern const char *output_return_instruction (rtx, bool, bool, bool);
+extern const char *output_probe_stack_range (rtx, rtx);
extern void arm_poke_function_name (FILE *, const char *);
extern void arm_final_prescan_insn (rtx_insn *);
extern int arm_debugger_arg_offset (int, rtx);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 62a63abc68f..b0239776b0c 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -61,6 +61,7 @@
#include "tm_p.h"
#include "target.h"
#include "sched-int.h"
+#include "common/common-target.h"
#include "debug.h"
#include "langhooks.h"
#include "intl.h"
@@ -3669,7 +3670,11 @@ use_return_insn (int iscond, rtx sibling)
/* Or if there is a stack adjustment. However, if the stack pointer
is saved on the stack, we can use a pre-incrementing stack load. */
|| !(stack_adjust == 0 || (TARGET_APCS_FRAME && frame_pointer_needed
- && stack_adjust == 4)))
+ && stack_adjust == 4))
+ /* Or if the static chain register was saved above the frame, under the
+ assumption that the stack pointer isn't saved on the stack. */
+ || (!(TARGET_APCS_FRAME && frame_pointer_needed)
+ && arm_compute_static_chain_stack_bytes() != 0))
return 0;
saved_int_regs = offsets->saved_regs_mask;
@@ -19174,8 +19179,10 @@ static int
arm_compute_static_chain_stack_bytes (void)
{
/* See the defining assertion in arm_expand_prologue. */
- if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM
- && IS_NESTED (arm_current_func_type ())
+ if (IS_NESTED (arm_current_func_type ())
+ && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+ || (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+ && !df_regs_ever_live_p (LR_REGNUM)))
&& arm_r3_live_at_start_p ()
&& crtl->args.pretend_args_size == 0)
return 4;
@@ -19270,7 +19277,6 @@ arm_compute_save_reg_mask (void)
return save_reg_mask;
}
-
/* Compute a bit mask of which registers need to be
saved on the stack for the current function. */
static unsigned long
@@ -21098,6 +21104,240 @@ thumb_set_frame_pointer (arm_stack_offsets *offsets)
RTX_FRAME_RELATED_P (insn) = 1;
}
+struct scratch_reg {
+ rtx reg;
+ bool saved;
+};
+
+/* Return a short-lived scratch register for use as a 2nd scratch register on
+ function entry after the registers are saved in the prologue. This register
+ must be released by means of release_scratch_register_on_entry. IP is not
+ considered since it is always used as the 1st scratch register if available.
+
+ REGNO1 is the index number of the 1st scratch register and LIVE_REGS is the
+ mask of live registers. */
+
+static void
+get_scratch_register_on_entry (struct scratch_reg *sr, unsigned int regno1,
+ unsigned long live_regs)
+{
+ int regno = -1;
+
+ sr->saved = false;
+
+ if (regno1 != LR_REGNUM && (live_regs & (1 << LR_REGNUM)) != 0)
+ regno = LR_REGNUM;
+ else
+ {
+ unsigned int i;
+
+ for (i = 4; i < 11; i++)
+ if (regno1 != i && (live_regs & (1 << i)) != 0)
+ {
+ regno = i;
+ break;
+ }
+
+ if (regno < 0)
+ {
+ /* If IP is used as the 1st scratch register for a nested function,
+ then either r3 wasn't available or is used to preserve IP. */
+ if (regno1 == IP_REGNUM && IS_NESTED (arm_current_func_type ()))
+ regno1 = 3;
+ regno = (regno1 == 3 ? 2 : 3);
+ sr->saved
+ = REGNO_REG_SET_P (df_get_live_out (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
+ regno);
+ }
+ }
+
+ sr->reg = gen_rtx_REG (SImode, regno);
+ if (sr->saved)
+ {
+ rtx addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
+ rtx insn = emit_set_insn (gen_frame_mem (SImode, addr), sr->reg);
+ rtx x = gen_rtx_SET (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx, -4));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, x);
+ }
+}
+
+/* Release a scratch register obtained from the preceding function. */
+
+static void
+release_scratch_register_on_entry (struct scratch_reg *sr)
+{
+ if (sr->saved)
+ {
+ rtx addr = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
+ rtx insn = emit_set_insn (sr->reg, gen_frame_mem (SImode, addr));
+ rtx x = gen_rtx_SET (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx, 4));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, x);
+ }
+}
+
+#define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
+
+#if PROBE_INTERVAL > 4096
+#error Cannot use indexed addressing mode for stack probing
+#endif
+
+/* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE,
+ inclusive. These are offsets from the current stack pointer. REGNO1
+ is the index number of the 1st scratch register and LIVE_REGS is the
+ mask of live registers. */
+
+static void
+arm_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size,
+ unsigned int regno1, unsigned long live_regs)
+{
+ rtx reg1 = gen_rtx_REG (Pmode, regno1);
+
+ /* See if we have a constant small number of probes to generate. If so,
+ that's the easy case. */
+ if (size <= PROBE_INTERVAL)
+ {
+ emit_move_insn (reg1, GEN_INT (first + PROBE_INTERVAL));
+ emit_set_insn (reg1, gen_rtx_MINUS (Pmode, stack_pointer_rtx, reg1));
+ emit_stack_probe (plus_constant (Pmode, reg1, PROBE_INTERVAL - size));
+ }
+
+ /* The run-time loop is made up of 10 insns in the generic case while the
+ compile-time loop is made up of 4+2*(n-2) insns for n # of intervals. */
+ else if (size <= 5 * PROBE_INTERVAL)
+ {
+ HOST_WIDE_INT i, rem;
+
+ emit_move_insn (reg1, GEN_INT (first + PROBE_INTERVAL));
+ emit_set_insn (reg1, gen_rtx_MINUS (Pmode, stack_pointer_rtx, reg1));
+ emit_stack_probe (reg1);
+
+ /* Probe at FIRST + N * PROBE_INTERVAL for values of N from 2 until
+ it exceeds SIZE. If only two probes are needed, this will not
+ generate any code. Then probe at FIRST + SIZE. */
+ for (i = 2 * PROBE_INTERVAL; i < size; i += PROBE_INTERVAL)
+ {
+ emit_set_insn (reg1, plus_constant (Pmode, reg1, -PROBE_INTERVAL));
+ emit_stack_probe (reg1);
+ }
+
+ rem = size - (i - PROBE_INTERVAL);
+ if (rem > 4095 || (TARGET_THUMB2 && rem > 255))
+ {
+ emit_set_insn (reg1, plus_constant (Pmode, reg1, -PROBE_INTERVAL));
+ emit_stack_probe (plus_constant (Pmode, reg1, PROBE_INTERVAL - rem));
+ }
+ else
+ emit_stack_probe (plus_constant (Pmode, reg1, -rem));
+ }
+
+ /* Otherwise, do the same as above, but in a loop. Note that we must be
+ extra careful with variables wrapping around because we might be at
+ the very top (or the very bottom) of the address space and we have
+ to be able to handle this case properly; in particular, we use an
+ equality test for the loop condition. */
+ else
+ {
+ HOST_WIDE_INT rounded_size;
+ struct scratch_reg sr;
+
+ get_scratch_register_on_entry (&sr, regno1, live_regs);
+
+ emit_move_insn (reg1, GEN_INT (first));
+
+
+ /* Step 1: round SIZE to the previous multiple of the interval. */
+
+ rounded_size = size & -PROBE_INTERVAL;
+ emit_move_insn (sr.reg, GEN_INT (rounded_size));
+
+
+ /* Step 2: compute initial and final value of the loop counter. */
+
+ /* TEST_ADDR = SP + FIRST. */
+ emit_set_insn (reg1, gen_rtx_MINUS (Pmode, stack_pointer_rtx, reg1));
+
+ /* LAST_ADDR = SP + FIRST + ROUNDED_SIZE. */
+ emit_set_insn (sr.reg, gen_rtx_MINUS (Pmode, reg1, sr.reg));
+
+
+ /* Step 3: the loop
+
+ while (TEST_ADDR != LAST_ADDR)
+ {
+ TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
+ probe at TEST_ADDR
+ }
+
+ probes at FIRST + N * PROBE_INTERVAL for values of N from 1
+ until it is equal to ROUNDED_SIZE. */
+
+ emit_insn (gen_probe_stack_range (reg1, reg1, sr.reg));
+
+
+ /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
+ that SIZE is equal to ROUNDED_SIZE. */
+
+ if (size != rounded_size)
+ {
+ HOST_WIDE_INT rem = size - rounded_size;
+
+ if (rem > 4095 || (TARGET_THUMB2 && rem > 255))
+ {
+ emit_set_insn (sr.reg,
+ plus_constant (Pmode, sr.reg, -PROBE_INTERVAL));
+ emit_stack_probe (plus_constant (Pmode, sr.reg,
+ PROBE_INTERVAL - rem));
+ }
+ else
+ emit_stack_probe (plus_constant (Pmode, sr.reg, -rem));
+ }
+
+ release_scratch_register_on_entry (&sr);
+ }
+
+ /* Make sure nothing is scheduled before we are done. */
+ emit_insn (gen_blockage ());
+}
+
+/* Probe a range of stack addresses from REG1 to REG2 inclusive. These are
+ absolute addresses. */
+
+const char *
+output_probe_stack_range (rtx reg1, rtx reg2)
+{
+ static int labelno = 0;
+ char loop_lab[32];
+ rtx xops[2];
+
+ ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
+
+ /* Test if TEST_ADDR == LAST_ADDR. */
+ xops[0] = reg1;
+ xops[1] = reg2;
+ output_asm_insn ("cmp\t%0, %1", xops);
+
+ if (TARGET_THUMB2)
+ fputs ("\tittt\tne\n", asm_out_file);
+
+ /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */
+ xops[1] = GEN_INT (PROBE_INTERVAL);
+ output_asm_insn ("subne\t%0, %0, %1", xops);
+
+ /* Probe at TEST_ADDR and branch. */
+ output_asm_insn ("strne\tr0, [%0, #0]", xops);
+ fputs ("\tbne\t", asm_out_file);
+ assemble_name_raw (asm_out_file, loop_lab);
+ fputc ('\n', asm_out_file);
+
+ return "";
+}
+
/* Generate the prologue instructions for entry into an ARM or Thumb-2
function. */
void
@@ -21112,7 +21352,9 @@ arm_expand_prologue (void)
int saved_pretend_args = 0;
int saved_regs = 0;
unsigned HOST_WIDE_INT args_to_push;
+ HOST_WIDE_INT size;
arm_stack_offsets *offsets;
+ bool clobber_ip;
func_type = arm_current_func_type ();
@@ -21163,109 +21405,108 @@ arm_expand_prologue (void)
emit_insn (gen_movsi (stack_pointer_rtx, r1));
}
- /* For APCS frames, if IP register is clobbered
- when creating frame, save that register in a special
- way. */
- if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+ /* The static chain register is the same as the IP register. If it is
+ clobbered when creating the frame, we need to save and restore it. */
+ clobber_ip = IS_NESTED (func_type)
+ && ((TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+ || (flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+ && !df_regs_ever_live_p (LR_REGNUM)
+ && arm_r3_live_at_start_p ()));
+
+ /* Find somewhere to store IP whilst the frame is being created.
+ We try the following places in order:
+
+ 1. The last argument register r3 if it is available.
+ 2. A slot on the stack above the frame if there are no
+ arguments to push onto the stack.
+ 3. Register r3 again, after pushing the argument registers
+ onto the stack, if this is a varargs function.
+ 4. The last slot on the stack created for the arguments to
+ push, if this isn't a varargs function.
+
+ Note - we only need to tell the dwarf2 backend about the SP
+ adjustment in the second variant; the static chain register
+ doesn't need to be unwound, as it doesn't contain a value
+ inherited from the caller. */
+ if (clobber_ip)
{
- if (IS_INTERRUPT (func_type))
+ if (!arm_r3_live_at_start_p ())
+ insn = emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
+ else if (args_to_push == 0)
{
- /* Interrupt functions must not corrupt any registers.
- Creating a frame pointer however, corrupts the IP
- register, so we must push it first. */
- emit_multi_reg_push (1 << IP_REGNUM, 1 << IP_REGNUM);
+ rtx addr, dwarf;
- /* Do not set RTX_FRAME_RELATED_P on this insn.
- The dwarf stack unwinding code only wants to see one
- stack decrement per function, and this is not it. If
- this instruction is labeled as being part of the frame
- creation sequence then dwarf2out_frame_debug_expr will
- die when it encounters the assignment of IP to FP
- later on, since the use of SP here establishes SP as
- the CFA register and not IP.
+ gcc_assert(arm_compute_static_chain_stack_bytes() == 4);
+ saved_regs += 4;
- Anyway this instruction is not really part of the stack
- frame creation although it is part of the prologue. */
+ addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
+ insn = emit_set_insn (gen_frame_mem (SImode, addr), ip_rtx);
+ fp_offset = 4;
+
+ /* Just tell the dwarf backend that we adjusted SP. */
+ dwarf = gen_rtx_SET (stack_pointer_rtx,
+ plus_constant (Pmode, stack_pointer_rtx,
+ -fp_offset));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf);
}
- else if (IS_NESTED (func_type))
- {
- /* The static chain register is the same as the IP register
- used as a scratch register during stack frame creation.
- To get around this need to find somewhere to store IP
- whilst the frame is being created. We try the following
- places in order:
-
- 1. The last argument register r3 if it is available.
- 2. A slot on the stack above the frame if there are no
- arguments to push onto the stack.
- 3. Register r3 again, after pushing the argument registers
- onto the stack, if this is a varargs function.
- 4. The last slot on the stack created for the arguments to
- push, if this isn't a varargs function.
-
- Note - we only need to tell the dwarf2 backend about the SP
- adjustment in the second variant; the static chain register
- doesn't need to be unwound, as it doesn't contain a value
- inherited from the caller. */
-
- if (!arm_r3_live_at_start_p ())
- insn = emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
- else if (args_to_push == 0)
+ else
+ {
+ /* Store the args on the stack. */
+ if (cfun->machine->uses_anonymous_args)
+ {
+ insn = emit_multi_reg_push ((0xf0 >> (args_to_push / 4)) & 0xf,
+ (0xf0 >> (args_to_push / 4)) & 0xf);
+ emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
+ saved_pretend_args = 1;
+ }
+ else
{
rtx addr, dwarf;
- gcc_assert(arm_compute_static_chain_stack_bytes() == 4);
- saved_regs += 4;
+ if (args_to_push == 4)
+ addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
+ else
+ addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
+ -args_to_push));
- addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
insn = emit_set_insn (gen_frame_mem (SImode, addr), ip_rtx);
- fp_offset = 4;
/* Just tell the dwarf backend that we adjusted SP. */
dwarf = gen_rtx_SET (stack_pointer_rtx,
plus_constant (Pmode, stack_pointer_rtx,
- -fp_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
+ -args_to_push));
add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf);
}
- else
- {
- /* Store the args on the stack. */
- if (cfun->machine->uses_anonymous_args)
- {
- insn
- = emit_multi_reg_push ((0xf0 >> (args_to_push / 4)) & 0xf,
- (0xf0 >> (args_to_push / 4)) & 0xf);
- emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
- saved_pretend_args = 1;
- }
- else
- {
- rtx addr, dwarf;
- if (args_to_push == 4)
- addr = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);
- else
- addr
- = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx,
- plus_constant (Pmode,
- stack_pointer_rtx,
- -args_to_push));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ fp_offset = args_to_push;
+ args_to_push = 0;
+ }
+ }
- insn = emit_set_insn (gen_frame_mem (SImode, addr), ip_rtx);
+ if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM)
+ {
+ if (IS_INTERRUPT (func_type))
+ {
+ /* Interrupt functions must not corrupt any registers.
+ Creating a frame pointer however, corrupts the IP
+ register, so we must push it first. */
+ emit_multi_reg_push (1 << IP_REGNUM, 1 << IP_REGNUM);
- /* Just tell the dwarf backend that we adjusted SP. */
- dwarf
- = gen_rtx_SET (stack_pointer_rtx,
- plus_constant (Pmode, stack_pointer_rtx,
- -args_to_push));
- add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf);
- }
+ /* Do not set RTX_FRAME_RELATED_P on this insn.
+ The dwarf stack unwinding code only wants to see one
+ stack decrement per function, and this is not it. If
+ this instruction is labeled as being part of the frame
+ creation sequence then dwarf2out_frame_debug_expr will
+ die when it encounters the assignment of IP to FP
+ later on, since the use of SP here establishes SP as
+ the CFA register and not IP.
- RTX_FRAME_RELATED_P (insn) = 1;
- fp_offset = args_to_push;
- args_to_push = 0;
- }
+ Anyway this instruction is not really part of the stack
+ frame creation although it is part of the prologue. */
}
insn = emit_set_insn (ip_rtx,
@@ -21364,34 +21605,60 @@ arm_expand_prologue (void)
insn = GEN_INT (-(4 + args_to_push + fp_offset));
insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, ip_rtx, insn));
RTX_FRAME_RELATED_P (insn) = 1;
-
- if (IS_NESTED (func_type))
- {
- /* Recover the static chain register. */
- if (!arm_r3_live_at_start_p () || saved_pretend_args)
- insn = gen_rtx_REG (SImode, 3);
- else
- {
- insn = plus_constant (Pmode, hard_frame_pointer_rtx, 4);
- insn = gen_frame_mem (SImode, insn);
- }
- emit_set_insn (ip_rtx, insn);
- /* Add a USE to stop propagate_one_insn() from barfing. */
- emit_insn (gen_force_register_use (ip_rtx));
- }
}
else
{
- insn = GEN_INT (saved_regs - 4);
+ insn = GEN_INT (saved_regs - (4 + fp_offset));
insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
stack_pointer_rtx, insn));
RTX_FRAME_RELATED_P (insn) = 1;
}
}
+ size = offsets->outgoing_args - offsets->saved_args;
if (flag_stack_usage_info)
- current_function_static_stack_size
- = offsets->outgoing_args - offsets->saved_args;
+ current_function_static_stack_size = size;
+
+ /* If this isn't an interrupt service routine and we have a frame, then do
+ stack checking. We use IP as the first scratch register, except for the
+ non-APCS nested functions if LR or r3 are available (see clobber_ip). */
+ if (!IS_INTERRUPT (func_type)
+ && flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+ {
+ unsigned int regno;
+
+ if (!IS_NESTED (func_type) || clobber_ip)
+ regno = IP_REGNUM;
+ else if (df_regs_ever_live_p (LR_REGNUM))
+ regno = LR_REGNUM;
+ else
+ regno = 3;
+
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+ arm_emit_probe_stack_range (STACK_CHECK_PROTECT,
+ size - STACK_CHECK_PROTECT,
+ regno, live_regs_mask);
+ }
+ else if (size > 0)
+ arm_emit_probe_stack_range (STACK_CHECK_PROTECT, size,
+ regno, live_regs_mask);
+ }
+
+ /* Recover the static chain register. */
+ if (clobber_ip)
+ {
+ if (!arm_r3_live_at_start_p () || saved_pretend_args)
+ insn = gen_rtx_REG (SImode, 3);
+ else
+ {
+ insn = plus_constant (Pmode, hard_frame_pointer_rtx, 4);
+ insn = gen_frame_mem (SImode, insn);
+ }
+ emit_set_insn (ip_rtx, insn);
+ emit_insn (gen_force_register_use (ip_rtx));
+ }
if (offsets->outgoing_args != offsets->saved_args + saved_regs)
{
@@ -24370,6 +24637,7 @@ thumb1_expand_prologue (void)
rtx_insn *insn;
HOST_WIDE_INT amount;
+ HOST_WIDE_INT size;
arm_stack_offsets *offsets;
unsigned long func_type;
int regno;
@@ -24604,9 +24872,13 @@ thumb1_expand_prologue (void)
emit_move_insn (gen_rtx_REG (Pmode, ARM_HARD_FRAME_POINTER_REGNUM),
stack_pointer_rtx);
+ size = offsets->outgoing_args - offsets->saved_args;
if (flag_stack_usage_info)
- current_function_static_stack_size
- = offsets->outgoing_args - offsets->saved_args;
+ current_function_static_stack_size = size;
+
+ /* If we have a frame, then do stack checking. FIXME: not implemented. */
+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK && size)
+ sorry ("-fstack-check=specific for THUMB1");
amount = offsets->outgoing_args - offsets->saved_regs;
amount -= 4 * thumb1_extra_regs_pushed (offsets, true);
@@ -25177,14 +25449,16 @@ arm_expand_epilogue (bool really_return)
return;
}
- if (crtl->args.pretend_args_size)
+ amount
+ = crtl->args.pretend_args_size + arm_compute_static_chain_stack_bytes();
+ if (amount)
{
int i, j;
rtx dwarf = NULL_RTX;
rtx_insn *tmp =
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
- GEN_INT (crtl->args.pretend_args_size)));
+ GEN_INT (amount)));
RTX_FRAME_RELATED_P (tmp) = 1;
@@ -25203,7 +25477,7 @@ arm_expand_epilogue (bool really_return)
}
REG_NOTES (tmp) = dwarf;
}
- arm_add_cfa_adjust_cfa_note (tmp, crtl->args.pretend_args_size,
+ arm_add_cfa_adjust_cfa_note (tmp, amount,
stack_pointer_rtx, stack_pointer_rtx);
}
@@ -27212,9 +27486,45 @@ arm_order_regs_for_local_alloc (void)
bool
arm_frame_pointer_required (void)
{
- return (cfun->has_nonlocal_label
- || SUBTARGET_FRAME_POINTER_REQUIRED
- || (TARGET_ARM && TARGET_APCS_FRAME && ! leaf_function_p ()));
+ if (SUBTARGET_FRAME_POINTER_REQUIRED)
+ return true;
+
+ /* If the function receives nonlocal gotos, it needs to save the frame
+ pointer in the nonlocal_goto_save_area object. */
+ if (cfun->has_nonlocal_label)
+ return true;
+
+ /* The frame pointer is required for non-leaf APCS frames. */
+ if (TARGET_ARM && TARGET_APCS_FRAME && !leaf_function_p ())
+ return true;
+
+ /* If we are probing the stack in the prologue, we will have a faulting
+ instruction prior to the stack adjustment and this requires a frame
+ pointer if we want to catch the exception using the EABI unwinder. */
+ if (!IS_INTERRUPT (arm_current_func_type ())
+ && flag_stack_check == STATIC_BUILTIN_STACK_CHECK
+ && arm_except_unwind_info (&global_options) == UI_TARGET
+ && cfun->can_throw_non_call_exceptions)
+ {
+ HOST_WIDE_INT size = get_frame_size ();
+
+ /* That's irrelevant if there is no stack adjustment. */
+ if (size <= 0)
+ return false;
+
+ /* That's relevant only if there is a stack probe. */
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ /* We don't have the final size of the frame so adjust. */
+ size += 32 * UNITS_PER_WORD;
+ if (size > PROBE_INTERVAL && size > STACK_CHECK_PROTECT)
+ return true;
+ }
+ else
+ return true;
+ }
+
+ return false;
}
/* Only thumb1 can't support conditional execution, so return true if
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 878576a3cd5..ad5b02e5589 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -7891,7 +7891,7 @@
/* Switch mode now when possible. */
if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
&& arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
- return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
+ return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
}"
@@ -8259,6 +8259,30 @@
(set_attr "type" "block")]
)
+(define_insn "probe_stack"
+ [(set (match_operand 0 "memory_operand" "=m")
+ (unspec [(const_int 0)] UNSPEC_PROBE_STACK))]
+ "TARGET_32BIT"
+{
+ return "str%?\\tr0, %0";
+}
+ [(set_attr "type" "store1")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "probe_stack_range"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "r")]
+ UNSPEC_PROBE_STACK_RANGE))]
+ "TARGET_32BIT"
+{
+ return output_probe_stack_range (operands[0], operands[2]);
+}
+ [(set_attr "type" "multiple")
+ (set_attr "conds" "clob")]
+)
+
(define_expand "casesi"
[(match_operand:SI 0 "s_register_operand" "") ; index to jump on
(match_operand:SI 1 "const_int_operand" "") ; lower bound
diff --git a/gcc/config/arm/linux-elf.h b/gcc/config/arm/linux-elf.h
index 49ad9543f26..297a83f1f77 100644
--- a/gcc/config/arm/linux-elf.h
+++ b/gcc/config/arm/linux-elf.h
@@ -124,3 +124,6 @@
to COPY relocated symbol in the executable. See PR65780. */
#undef TARGET_BINDS_LOCAL_P
#define TARGET_BINDS_LOCAL_P default_binds_local_p_2
+
+/* Define this to be nonzero if static stack checking is supported. */
+#define STACK_CHECK_STATIC_BUILTIN 1
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 0ec2c48abea..44d4e7dae8a 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -83,6 +83,8 @@
; FPSCR rounding mode and signal inexactness.
UNSPEC_VRINTA ; Represent a float to integral float rounding
; towards nearest, ties away from zero.
+ UNSPEC_PROBE_STACK ; Probe stack memory reference
+ UNSPEC_PROBE_STACK_RANGE ; Probe stack range
])
(define_c_enum "unspec" [
diff --git a/gcc/config/ft32/ft32.c b/gcc/config/ft32/ft32.c
index f2e2677b2de..95df59676ab 100644
--- a/gcc/config/ft32/ft32.c
+++ b/gcc/config/ft32/ft32.c
@@ -745,12 +745,8 @@ ft32_arg_partial_bytes (cumulative_args_t cum_v,
int
ft32_is_mem_pm (rtx o)
{
- if (GET_CODE (o) != MEM)
- return false;
- if (MEM_EXPR (o))
- return TYPE_ADDR_SPACE (TREE_TYPE (MEM_EXPR (o))) == ADDR_SPACE_PM;
- else
- return MEM_ADDR_SPACE (o) == ADDR_SPACE_PM;
+ return (MEM_P (o)
+ && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (o)));
}
/* The Global `targetm' Variable. */
diff --git a/gcc/config/i386/i386-interix.h b/gcc/config/i386/i386-interix.h
index b472d8e9fe6..97dbcd97ef5 100644
--- a/gcc/config/i386/i386-interix.h
+++ b/gcc/config/i386/i386-interix.h
@@ -153,8 +153,6 @@ do { \
#define drectve_section() /* nothing */
-#define EH_FRAME_IN_DATA_SECTION
-
#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rdata,\"r\""
/* Define this macro if references to a symbol must be treated
@@ -326,7 +324,8 @@ while (0)
: ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (int) (n)+8 \
: (int) (-1))
-#define EH_FRAME_IN_DATA_SECTION
+#define EH_FRAME_THROUGH_COLLECT2
+#define EH_TABLES_CAN_BE_READ_ONLY 0
/* the following are OSF linker (not gld) specific... we don't want them */
#undef HAS_INIT_SECTION
diff --git a/gcc/config/rs6000/aix61.h b/gcc/config/rs6000/aix61.h
index ba48069c1fb..0e27057027f 100644
--- a/gcc/config/rs6000/aix61.h
+++ b/gcc/config/rs6000/aix61.h
@@ -167,7 +167,7 @@ do { \
%{!maix64:\
%{pthread:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\
%{!pthread:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}\
- %{shared:crtcxa_s%O%s;:crtcxa%O%s}"
+ %{shared:crtcxa_s%O%s;:crtcxa%O%s} crtdbase%O%s"
/* AIX V5 typedefs ptrdiff_t as "long" while earlier releases used "int". */
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 7be529fab49..82a695c06b6 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -203,6 +203,10 @@ extern void rs6000_aix_asm_output_dwarf_table_ref (char *);
extern void get_ppc476_thunk_name (char name[32]);
extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins);
extern HOST_WIDE_INT rs6000_builtin_mask_calculate (void);
+extern void rs6000_asm_output_dwarf_pcrel (FILE *file, int size,
+ const char *label);
+extern void rs6000_asm_output_dwarf_datarel (FILE *file, int size,
+ const char *label);
/* Declare functions in rs6000-c.c */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 7278792d0dc..8a22af62962 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -30790,7 +30790,6 @@ rs6000_xcoff_asm_init_sections (void)
= get_unnamed_section (0, rs6000_xcoff_output_toc_section_asm_op, NULL);
readonly_data_section = read_only_data_section;
- exception_section = data_section;
}
static int
@@ -31159,6 +31158,31 @@ rs6000_xcoff_declare_object_name (FILE *file, const char *name, tree decl)
symtab_node::get (decl)->call_for_symbol_and_aliases (rs6000_declare_alias, &data, true);
}
+/* Overide the default 'SYMBOL-.' syntax with AIX compatible 'SYMBOL-$'. */
+
+void
+rs6000_asm_output_dwarf_pcrel (FILE *file, int size, const char *label)
+{
+ fputs (integer_asm_op (size, FALSE), file);
+ assemble_name (file, label);
+ fputs ("-$", file);
+}
+
+/* Output a symbol offset relative to the dbase for the current object.
+ We use __gcc_unwind_dbase as an arbitrary base for dbase and assume
+ signed offsets.
+
+ __gcc_unwind_dbase is embedded in all executables/libraries through
+ libgcc/config/rs6000/crtdbase.S. */
+
+void
+rs6000_asm_output_dwarf_datarel (FILE *file, int size, const char *label)
+{
+ fputs (integer_asm_op (size, FALSE), file);
+ assemble_name (file, label);
+ fputs("-__gcc_unwind_dbase", file);
+}
+
#ifdef HAVE_AS_TLS
static void
rs6000_xcoff_encode_section_info (tree decl, rtx rtl, int first)
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 25149a60ff7..ec0abc59a8b 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -4659,7 +4659,7 @@ typedef struct label_ref_list_d
} *label_ref_list_t;
static object_allocator<label_ref_list_d> label_ref_list_d_pool
- ("label references list", 30);
+ ("label references list");
/* The SH cannot load a large constant into a register, constants have to
come from a pc relative load. The reference of a pc relative load
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 4e7cd169f84..659c4c78b30 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -9464,7 +9464,7 @@ label:
(use (reg:SI FPSCR_MODES_REG))
(use (reg:SI PIC_REG))
(clobber (reg:SI PR_REG))
- (clobber (match_scratch:SI 2 "=r"))]
+ (clobber (match_scratch:SI 2 "=&r"))]
"TARGET_SH2"
"#"
"reload_completed"
@@ -9595,7 +9595,7 @@ label:
(use (reg:SI FPSCR_MODES_REG))
(use (reg:SI PIC_REG))
(clobber (reg:SI PR_REG))
- (clobber (match_scratch:SI 3 "=r"))]
+ (clobber (match_scratch:SI 3 "=&r"))]
"TARGET_SH2"
"#"
"reload_completed"
@@ -9993,7 +9993,7 @@ label:
[(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" ""))
(match_operand 1 "" ""))
(use (reg:SI FPSCR_MODES_REG))
- (clobber (match_scratch:SI 2 "=k"))
+ (clobber (match_scratch:SI 2 "=&k"))
(return)]
"TARGET_SH2"
"#"
@@ -10185,7 +10185,7 @@ label:
(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" ""))
(match_operand 2 "" "")))
(use (reg:SI FPSCR_MODES_REG))
- (clobber (match_scratch:SI 3 "=k"))
+ (clobber (match_scratch:SI 3 "=&k"))
(return)]
"TARGET_SH2"
"#"
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index 143143709d1..18192fd2e8d 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -62,6 +62,8 @@ extern bool constant_address_p (rtx);
extern bool legitimate_pic_operand_p (rtx);
extern rtx sparc_legitimize_reload_address (rtx, machine_mode, int, int,
int, int *win);
+extern bool sparc_secondary_memory_needed (enum reg_class, enum reg_class,
+ machine_mode);
extern void load_got_register (void);
extern void sparc_emit_call_insn (rtx, rtx);
extern void sparc_defer_case_vector (rtx, rtx, int);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index ed8a1665e6a..85378dddf5c 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -12278,6 +12278,26 @@ sparc_expand_vector_init (rtx target, rtx vals)
emit_move_insn (target, mem);
}
+bool sparc_secondary_memory_needed (enum reg_class class1, enum reg_class class2,
+ machine_mode mode)
+{
+ if (FP_REG_CLASS_P (class1) != FP_REG_CLASS_P (class2))
+ {
+ if (! TARGET_VIS3
+ || GET_MODE_SIZE (mode) > 8
+ || GET_MODE_SIZE (mode) < 4)
+ return true;
+ return false;
+ }
+
+ if (GET_MODE_SIZE (mode) == 4
+ && ((class1 == FP_REGS && class2 == EXTRA_FP_REGS)
+ || (class1 == EXTRA_FP_REGS && class2 == FP_REGS)))
+ return true;
+
+ return false;
+}
+
/* Implement TARGET_SECONDARY_RELOAD. */
static reg_class_t
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 2cbe0d9b7fa..a447940c4e2 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -736,6 +736,12 @@ extern int sparc_mode_class[];
register window instruction in the prologue. */
#define HARD_REGNO_RENAME_OK(FROM, TO) ((FROM) != 1)
+/* Select a register mode required for caller save of hard regno REGNO. */
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
+ (((MODE) == VOIDmode) ? \
+ choose_hard_reg_mode ((REGNO), (NREGS), false) : \
+ (MODE))
+
#define MODES_TIEABLE_P(MODE1, MODE2) sparc_modes_tieable_p (MODE1, MODE2)
/* Specify the registers used for certain standard purposes.
@@ -1033,12 +1039,10 @@ extern char leaf_reg_remap[];
(SPARC_SETHI_P ((unsigned HOST_WIDE_INT) (X) & GET_MODE_MASK (SImode)))
/* On SPARC when not VIS3 it is not possible to directly move data
- between GENERAL_REGS and FP_REGS. */
+ between GENERAL_REGS and FP_REGS. We also cannot move 4-byte values
+ between FP_REGS and EXTRA_FP_REGS. */
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
- ((FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2)) \
- && (! TARGET_VIS3 \
- || GET_MODE_SIZE (MODE) > 8 \
- || GET_MODE_SIZE (MODE) < 4))
+ sparc_secondary_memory_needed (CLASS1, CLASS2, MODE)
/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
because the movsi and movsf patterns don't handle r/f moves.
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 5b9f0517b90..bc8d782e2c8 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -1745,105 +1745,105 @@
(define_insn "*sethi_di_medlow"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (match_operand:DI 1 "symbolic_operand" "")))]
- "TARGET_CM_MEDLOW && check_pic (1)"
+ "TARGET_CM_MEDLOW && !flag_pic"
"sethi\t%%hi(%a1), %0")
(define_insn "*losum_di_medlow"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "symbolic_operand" "")))]
- "TARGET_CM_MEDLOW"
+ "TARGET_CM_MEDLOW && !flag_pic"
"or\t%1, %%lo(%a2), %0")
(define_insn "seth44"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETH44)))]
- "TARGET_CM_MEDMID"
+ "TARGET_CM_MEDMID && !flag_pic"
"sethi\t%%h44(%a1), %0")
(define_insn "setm44"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_SETM44)))]
- "TARGET_CM_MEDMID"
+ "TARGET_CM_MEDMID && !flag_pic"
"or\t%1, %%m44(%a2), %0")
(define_insn "setl44"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "symbolic_operand" "")))]
- "TARGET_CM_MEDMID"
+ "TARGET_CM_MEDMID && !flag_pic"
"or\t%1, %%l44(%a2), %0")
(define_insn "sethh"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETHH)))]
- "TARGET_CM_MEDANY"
+ "TARGET_CM_MEDANY && !flag_pic"
"sethi\t%%hh(%a1), %0")
(define_insn "setlm"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] UNSPEC_SETLM)))]
- "TARGET_CM_MEDANY"
+ "TARGET_CM_MEDANY && !flag_pic"
"sethi\t%%lm(%a1), %0")
(define_insn "sethm"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] UNSPEC_EMB_SETHM)))]
- "TARGET_CM_MEDANY"
+ "TARGET_CM_MEDANY && !flag_pic"
"or\t%1, %%hm(%a2), %0")
(define_insn "setlo"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "symbolic_operand" "")))]
- "TARGET_CM_MEDANY"
+ "TARGET_CM_MEDANY && !flag_pic"
"or\t%1, %%lo(%a2), %0")
(define_insn "embmedany_sethi"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "data_segment_operand" "")] UNSPEC_EMB_HISUM)))]
- "TARGET_CM_EMBMEDANY && check_pic (1)"
+ "TARGET_CM_EMBMEDANY && !flag_pic"
"sethi\t%%hi(%a1), %0")
(define_insn "embmedany_losum"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "data_segment_operand" "")))]
- "TARGET_CM_EMBMEDANY"
+ "TARGET_CM_EMBMEDANY && !flag_pic"
"add\t%1, %%lo(%a2), %0")
(define_insn "embmedany_brsum"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_EMB_HISUM))]
- "TARGET_CM_EMBMEDANY"
+ "TARGET_CM_EMBMEDANY && !flag_pic"
"add\t%1, %_, %0")
(define_insn "embmedany_textuhi"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTUHI)))]
- "TARGET_CM_EMBMEDANY && check_pic (1)"
+ "TARGET_CM_EMBMEDANY && !flag_pic"
"sethi\t%%uhi(%a1), %0")
(define_insn "embmedany_texthi"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (unspec:DI [(match_operand:DI 1 "text_segment_operand" "")] UNSPEC_EMB_TEXTHI)))]
- "TARGET_CM_EMBMEDANY && check_pic (1)"
+ "TARGET_CM_EMBMEDANY && !flag_pic"
"sethi\t%%hi(%a1), %0")
(define_insn "embmedany_textulo"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(unspec:DI [(match_operand:DI 2 "text_segment_operand" "")] UNSPEC_EMB_TEXTULO)))]
- "TARGET_CM_EMBMEDANY"
+ "TARGET_CM_EMBMEDANY && !flag_pic"
"or\t%1, %%ulo(%a2), %0")
(define_insn "embmedany_textlo"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "text_segment_operand" "")))]
- "TARGET_CM_EMBMEDANY"
+ "TARGET_CM_EMBMEDANY && !flag_pic"
"or\t%1, %%lo(%a2), %0")
;; Now some patterns to help reload out a bit.
diff --git a/gcc/config/spu/spu-elf.h b/gcc/config/spu/spu-elf.h
index c5098706c66..46d35016af0 100644
--- a/gcc/config/spu/spu-elf.h
+++ b/gcc/config/spu/spu-elf.h
@@ -61,7 +61,7 @@
#undef TARGET_ASM_NAMED_SECTION
#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
-#define EH_FRAME_IN_DATA_SECTION 1
+#define EH_FRAME_THROUGH_COLLECT2 1
#define LINK_SPEC "%{mlarge-mem: --defsym __stack=0xfffffff0 }"