This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
ARM ISR routines. [v2]
Hi Guys,
OK, I have been persuaded that we need to support using the frame
pointer inside interrupt handler functions, so he is the modified
patch. The patch is the same as the last one except that now if the
frame pointer is needed (including the case twhen stack frames are
requested) the code will push the IP register before corrupting and
then pop it at the end of the function.
I have applied this version of the patch.
Cheers
Nick
2001-06-24 Nick Clifton <nickc@cambridge.redhat.com>
* 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.
Index: arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.147
diff -p -r1.147 arm.c
*** arm.c 2001/06/22 17:38:19 1.147
--- arm.c 2001/06/24 09:37:40
*************** Boston, MA 02111-1307, USA. */
*** 43,48 ****
--- 43,49 ----
#include "ggc.h"
#include "except.h"
#include "c-pragma.h"
+ #include "integrate.h"
#include "tm_p.h"
/* Forward definitions of types. */
*************** arm_compute_save_reg_mask ()
*** 6931,6942 ****
if (IS_VOLATILE (func_type))
return save_reg_mask;
! if (ARM_FUNC_TYPE (func_type) == ARM_FT_ISR)
{
! /* 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])
save_reg_mask |= (1 << reg);
}
else
--- 6932,6960 ----
if (IS_VOLATILE (func_type))
return save_reg_mask;
! if (IS_INTERRUPT (func_type))
{
! 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
*************** arm_output_epilogue (really_return)
*** 7410,7415 ****
--- 7428,7438 ----
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
{
*************** arm_expand_prologue ()
*** 7783,7789 ****
if (frame_pointer_needed)
{
! 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.
--- 7806,7820 ----
if (frame_pointer_needed)
{
! 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.
*************** replace_symbols_in_block (block, orig, n
*** 8925,8931 ****
)
continue;
! DECL_RTL (sym) = new;
}
replace_symbols_in_block (BLOCK_SUBBLOCKS (block), orig, new);
--- 8956,8962 ----
)
continue;
! SET_DECL_RTL (sym, new);
}
replace_symbols_in_block (BLOCK_SUBBLOCKS (block), orig, new);
Index: arm.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.105
diff -p -r1.105 arm.h
*** arm.h 2001/06/22 17:38:19 1.105
--- arm.h 2001/06/24 09:37:45
*************** extern const char * structure_size_strin
*** 969,976 ****
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 \
|| (TARGET_ARM && TARGET_APCS_FRAME && ! leaf_function_p ()))
/* Return number of consecutive hard regs needed starting at reg REGNO
--- 969,976 ----
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 \
|| (TARGET_ARM && TARGET_APCS_FRAME && ! leaf_function_p ()))
/* Return number of consecutive hard regs needed starting at reg REGNO
*************** extern int making_const_table;
*** 2758,2769 ****
#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)) \
: 0))))
/* Output the address of an operand. */
--- 2758,2769 ----
#define HOST_UINT(x) ((unsigned HOST_WIDE_INT) x)
#endif
! #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. */