+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.
+
2001-06-23 Richard Henderson <rth@redhat.com>
* config/alpha/crtfastmath.c: New file.
#include "ggc.h"
#include "except.h"
#include "c-pragma.h"
+#include "integrate.h"
#include "tm_p.h"
/* Forward definitions of types. */
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
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
{
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.
)
continue;
- DECL_RTL (sym) = new;
+ SET_DECL_RTL (sym, new);
}
replace_symbols_in_block (BLOCK_SUBBLOCKS (block), orig, new);
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
#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. */