diff options
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r-- | gcc/config/arm/arm.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 5974c65d31..24b204a1d4 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -6704,7 +6704,7 @@ arm_function_ok_for_sibcall (tree decl, tree exp) /* The PIC register is live on entry to VxWorks PLT entries, so we must make the call before restoring the PIC register. */ - if (TARGET_VXWORKS_RTP && flag_pic && !targetm.binds_local_p (decl)) + if (TARGET_VXWORKS_RTP && flag_pic && decl && !targetm.binds_local_p (decl)) return false; /* If we are interworking and the function is not declared static @@ -17755,6 +17755,7 @@ arm_output_multireg_pop (rtx *operands, bool return_pc, rtx cond, bool reverse, int num_saves = XVECLEN (operands[0], 0); unsigned int regno; unsigned int regno_base = REGNO (operands[1]); + bool interrupt_p = IS_INTERRUPT (arm_current_func_type ()); offset = 0; offset += update ? 1 : 0; @@ -17772,20 +17773,16 @@ arm_output_multireg_pop (rtx *operands, bool return_pc, rtx cond, bool reverse, } conditional = reverse ? "%?%D0" : "%?%d0"; - if ((regno_base == SP_REGNUM) && update) - { - sprintf (pattern, "pop%s\t{", conditional); - } + /* Can't use POP if returning from an interrupt. */ + if ((regno_base == SP_REGNUM) && update && !(interrupt_p && return_pc)) + sprintf (pattern, "pop%s\t{", conditional); else { /* Output ldmfd when the base register is SP, otherwise output ldmia. It's just a convention, their semantics are identical. */ if (regno_base == SP_REGNUM) - /* update is never true here, hence there is no need to handle - pop here. */ - sprintf (pattern, "ldmfd%s", conditional); - - if (update) + sprintf (pattern, "ldmfd%s\t", conditional); + else if (update) sprintf (pattern, "ldmia%s\t", conditional); else sprintf (pattern, "ldm%s\t", conditional); @@ -17811,7 +17808,7 @@ arm_output_multireg_pop (rtx *operands, bool return_pc, rtx cond, bool reverse, strcat (pattern, "}"); - if (IS_INTERRUPT (arm_current_func_type ()) && return_pc) + if (interrupt_p && return_pc) strcat (pattern, "^"); output_asm_insn (pattern, &cond); @@ -19622,8 +19619,12 @@ output_return_instruction (rtx operand, bool really_return, bool reverse, sprintf (instr, "ldmfd%s\t%%|sp, {", conditional); } } + /* For interrupt returns we have to use an LDM rather than + a POP so that we can use the exception return variant. */ + else if (IS_INTERRUPT (func_type)) + sprintf (instr, "ldmfd%s\t%%|sp!, {", conditional); else - sprintf (instr, "pop%s\t{", conditional); + sprintf (instr, "pop%s\t{", conditional); p = instr + strlen (instr); @@ -21461,7 +21462,11 @@ arm_expand_prologue (void) /* Naked functions don't have prologues. */ if (IS_NAKED (func_type)) - return; + { + if (flag_stack_usage_info) + current_function_static_stack_size = 0; + return; + } /* Make a copy of c_f_p_a_s as we may need to modify it locally. */ args_to_push = crtl->args.pretend_args_size; @@ -24715,7 +24720,11 @@ thumb1_expand_prologue (void) /* Naked functions don't have prologues. */ if (IS_NAKED (func_type)) - return; + { + if (flag_stack_usage_info) + current_function_static_stack_size = 0; + return; + } if (IS_INTERRUPT (func_type)) { |