From 7b8b8ade895d4483a53f1bb6ca6eba893d38e9ef Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Sun, 24 Jun 2001 09:46:02 +0000 Subject: [PATCH] Fix oinitialisation of frame pointer in interrupt functions. Fix compile time warnings From-SVN: r43540 --- gcc/ChangeLog | 14 ++++++++++++++ gcc/config/arm/arm.c | 45 +++++++++++++++++++++++++++++++++++++------- gcc/config/arm/arm.h | 16 ++++++++-------- 3 files changed, 60 insertions(+), 15 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5acd57cff2..d0ad198fa17 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2001-06-24 Nick Clifton + + * config/arm/arm.c (arm_compute_save_reg_mask): For FIQ interrupt + handlers examine register r0-r7, for other interrupt handlers + examine r0-r12. If the interrupt handler is not a leaf function + save all call clobbered registers. + (arm_output_epilogue): If the prologue has pushed the IP register, + restore it here. + (Arm_expand_prologue): For interrupt functions that need the frame + pointer, push the IP register before it is corrupted. + + * config/arm/arm.h (ARM_SIGN_EXTEND): Fix compile time warnings + about the use of signed and unsigned quantities in a conditional. + 2001-06-23 Richard Henderson * config/alpha/crtfastmath.c: New file. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index a1ce9c0f53c..c1f78873350 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -43,6 +43,7 @@ Boston, MA 02111-1307, USA. */ #include "ggc.h" #include "except.h" #include "c-pragma.h" +#include "integrate.h" #include "tm_p.h" /* Forward definitions of types. */ @@ -6931,12 +6932,29 @@ arm_compute_save_reg_mask () if (IS_VOLATILE (func_type)) return save_reg_mask; - if (ARM_FUNC_TYPE (func_type) == ARM_FT_ISR) + if (IS_INTERRUPT (func_type)) { - /* FIQ handlers have registers r8 - r12 banked, so - we only need to check r0 - r7, they must save them. */ - for (reg = 0; reg < 8; reg++) - if (regs_ever_live[reg]) + unsigned int max_reg; + + /* Interrupt functions must not corrupt any registers, + even call clobbered ones. If this is a leaf function + we can just examine the registers used by the RTL, but + otherwise we have to assume that whatever function is + called might clobber anything, and so we have to save + all the call-clobbered registers as well. */ + if (ARM_FUNC_TYPE (func_type) == ARM_FT_FIQ) + /* FIQ handlers have registers r8 - r12 banked, so + we only need to check r0 - r7, Normal ISRs only + bank r14 and r15, so ew must check up to r12. + r13 is the stack pointer which is always preserved, + so we do not need to consider it here. */ + max_reg = 7; + else + max_reg = 12; + + for (reg = 0; reg <= max_reg; reg++) + if (regs_ever_live[reg] + || (! current_function_is_leaf && call_used_regs [reg])) save_reg_mask |= (1 << reg); } else @@ -7410,6 +7428,11 @@ arm_output_epilogue (really_return) saved_regs_mask &= ~ (1 << PC_REGNUM); print_multi_reg (f, "ldmea\t%r", FP_REGNUM, saved_regs_mask); + + if (IS_INTERRUPT (func_type)) + /* Interrupt handlers will have pushed the + IP onto the stack, so restore it now. */ + print_multi_reg (f, "ldmea\t%r", SP_REGNUM, 1 << IP_REGNUM); } else { @@ -7783,7 +7806,15 @@ arm_expand_prologue () if (frame_pointer_needed) { - if (IS_NESTED (func_type)) + 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. */ + insn = emit_multi_reg_push (1 << IP_REGNUM); + RTX_FRAME_RELATED_P (insn) = 1; + } + 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. @@ -8925,7 +8956,7 @@ replace_symbols_in_block (block, orig, new) ) continue; - DECL_RTL (sym) = new; + SET_DECL_RTL (sym, new); } replace_symbols_in_block (BLOCK_SUBBLOCKS (block), orig, new); diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 8cd8b93f448..ed444db8029 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -969,8 +969,8 @@ extern const char * structure_size_string; If we have to have a frame pointer we might as well make use of it. APCS says that the frame pointer does not need to be pushed in leaf functions, or simple tail call functions. */ -#define FRAME_POINTER_REQUIRED \ - (current_function_has_nonlocal_label \ +#define FRAME_POINTER_REQUIRED \ + (current_function_has_nonlocal_label \ || (TARGET_ARM && TARGET_APCS_FRAME && ! leaf_function_p ())) /* Return number of consecutive hard regs needed starting at reg REGNO @@ -2758,12 +2758,12 @@ extern int making_const_table; #define HOST_UINT(x) ((unsigned HOST_WIDE_INT) x) #endif -#define ARM_SIGN_EXTEND(x) ((HOST_WIDE_INT) \ - (HOST_BITS_PER_WIDE_INT <= 32 ? (x) \ - : (((x) & HOST_UINT (0xffffffff)) | \ - (((x) & HOST_UINT (0x80000000)) \ - ? ((~ HOST_INT (0)) \ - & ~ HOST_UINT(0xffffffff)) \ +#define ARM_SIGN_EXTEND(x) ((HOST_WIDE_INT) \ + (HOST_BITS_PER_WIDE_INT <= 32 ? (unsigned HOST_WIDE_INT) (x) \ + : ((((unsigned HOST_WIDE_INT)(x)) & HOST_UINT (0xffffffff)) |\ + ((((unsigned HOST_WIDE_INT)(x)) & HOST_UINT (0x80000000)) \ + ? ((~ HOST_UINT (0)) \ + & ~ HOST_UINT(0xffffffff)) \ : 0)))) /* Output the address of an operand. */