diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-11 06:07:51 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-11 06:07:51 +0000 |
commit | 7f343dad554f0166f664cba7d6ab809ee4473f13 (patch) | |
tree | 5f549f9387f37ae57d7747549dd4403b83905370 /gcc/config | |
parent | efdfa4676cd3506381bd987f7365767bb05c934a (diff) | |
download | gcc-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.md | 46 | ||||
-rw-r--r-- | gcc/config/arm/arm-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 536 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 26 | ||||
-rw-r--r-- | gcc/config/arm/linux-elf.h | 3 | ||||
-rw-r--r-- | gcc/config/arm/unspecs.md | 2 | ||||
-rw-r--r-- | gcc/config/ft32/ft32.c | 8 | ||||
-rw-r--r-- | gcc/config/i386/i386-interix.h | 5 | ||||
-rw-r--r-- | gcc/config/rs6000/aix61.h | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 26 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 2 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 8 | ||||
-rw-r--r-- | gcc/config/sparc/sparc-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.c | 20 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.h | 14 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 32 | ||||
-rw-r--r-- | gcc/config/spu/spu-elf.h | 2 |
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 }" |