ARM7TDMI: get rid of gcc's __attribute__((interrupt)).
[bertos.git] / bertos / cpu / irq.h
index c3824556176b647068a5e6913b19c122b102e3a5..6eac70fdea50424752119224ac1165fc794f3a50 100644 (file)
 
        #else /* !__IAR_SYSTEMS_ICC__ */
 
-               #define IRQ_DISABLE \
-               do { \
-                       asm volatile ( \
-                               "mrs r0, cpsr\n\t" \
-                               "orr r0, r0, #0xc0\n\t" \
-                               "msr cpsr_c, r0" \
-                               ::: "r0" \
-                       ); \
+               #define IRQ_DISABLE                                     \
+               do {                                                    \
+                       cpu_flags_t sreg;                               \
+                       asm volatile (                                  \
+                               "mrs %0, cpsr\n\t"                      \
+                               "orr %0, %0, #0xc0\n\t"                 \
+                               "msr cpsr_c, %0\n\t"                    \
+                               : "=r" (sreg) : : "memory", "cc");      \
                } while (0)
 
-               #define IRQ_ENABLE \
-               do { \
-                       asm volatile ( \
-                               "mrs r0, cpsr\n\t" \
-                               "bic r0, r0, #0xc0\n\t" \
-                               "msr cpsr_c, r0" \
-                               ::: "r0" \
-                       ); \
+               #define IRQ_ENABLE                                      \
+               do {                                                    \
+                       cpu_flags_t sreg;                               \
+                       asm volatile (                                  \
+                               "mrs %0, cpsr\n\t"                      \
+                               "bic %0, %0, #0xc0\n\t"                 \
+                               "msr cpsr_c, %0\n\t"                    \
+                               : "=r" (sreg) : : "memory", "cc");      \
                } while (0)
 
-               #define IRQ_SAVE_DISABLE(x) \
-               do { \
-                       asm volatile ( \
-                               "mrs %0, cpsr\n\t" \
-                               "orr r0, %0, #0xc0\n\t" \
-                               "msr cpsr_c, r0" \
-                               : "=r" (x) \
-                               : /* no inputs */ \
-                               : "r0" \
-                       ); \
+               #define IRQ_SAVE_DISABLE(x)                             \
+               do {                                                    \
+                       register cpu_flags_t sreg;                      \
+                       asm volatile (                                  \
+                               "mrs %0, cpsr\n\t"                      \
+                               "orr %1, %0, #0xc0\n\t"                 \
+                               "msr cpsr_c, %1\n\t"                    \
+                               : "=r" (x), "=r" (sreg)                 \
+                               : : "memory", "cc");                    \
                } while (0)
 
-               #define IRQ_RESTORE(x) \
-               do { \
-                       asm volatile ( \
-                               "msr cpsr_c, %0" \
-                               : /* no outputs */ \
-                               : "r" (x) \
-                       ); \
+               #define IRQ_RESTORE(x)                                  \
+               do {                                                    \
+                       asm volatile (                                  \
+                               "msr cpsr_c, %0\n\t"                    \
+                               : : "r" (x) : "memory", "cc");          \
                } while (0)
 
-               #define CPU_READ_FLAGS() \
-               ({ \
-                       cpu_flags_t sreg; \
-                       asm volatile ( \
-                               "mrs %0, cpsr\n\t" \
-                               : "=r" (sreg) \
-                               : /* no inputs */ \
-                       ); \
-                       sreg; \
+               #define CPU_READ_FLAGS()                                \
+               ({                                                      \
+                       cpu_flags_t sreg;                               \
+                       asm volatile (                                  \
+                               "mrs %0, cpsr\n\t"                      \
+                               : "=r" (sreg) : : "memory", "cc");      \
+                       sreg;                                           \
                })
 
                #define IRQ_ENABLED() ((CPU_READ_FLAGS() & 0xc0) != 0xc0)
                         * IRQs will be automatically re-enabled when restoring
                         * the context of the user task.
                         */
-                       #define DECLARE_ISR_CONTEXT_SWITCH(func)        \
-                               void ISR_FUNC func(void);               \
-                               static void __isr_##func(void);         \
-                               void ISR_FUNC func(void)                \
-                               {                                       \
-                                       IRQ_ENTRY();                    \
-                                       IRQ_DISABLE;                    \
-                                       __isr_##func();                 \
-                                       IRQ_EXIT();                     \
-                               }                                       \
-                               static void __isr_##func(void)
+                       #define DECLARE_ISR_CONTEXT_SWITCH(func)                \
+                               void ISR_FUNC func(void);                       \
+                               static NOINLINE void __isr_##func(void);        \
+                               void ISR_FUNC func(void)                        \
+                               {                                               \
+                                       IRQ_ENTRY();                            \
+                                       IRQ_DISABLE;                            \
+                                       __isr_##func();                         \
+                                       IRQ_EXIT();                             \
+                               }                                               \
+                               static NOINLINE void __isr_##func(void)
                        /**
                         * Interrupt service routine prototype: can be used for
                         * forward declarations.
                        #endif /* !CONFIG_KERN_PRI */
                #endif /* CONFIG_KERN_PREEMPT */
 
+               #ifndef ISR_FUNC
+                       #define ISR_FUNC __attribute__((naked))
+               #endif
                #ifndef DECLARE_ISR
                        #define DECLARE_ISR(func) \
-                               void __attribute__((interrupt)) func(void)
+                               void ISR_FUNC func(void);                               \
+                               /*                                                      \
+                                * FIXME: avoid the inlining of this function.          \
+                                *                                                      \
+                                * This is terribly inefficient, but it's a             \
+                                * reliable workaround to avoid gcc blowing             \
+                                * away the stack (see the bug below):                  \
+                                *                                                      \
+                                * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41999    \
+                                */                                                     \
+                               static NOINLINE void __isr_##func(void);                \
+                               void ISR_FUNC func(void)                                \
+                               {                                                       \
+                                       asm volatile (                                  \
+                                               "sub    lr, lr, #4\n\t"                 \
+                                               "stmfd  sp!, {r0-r3, ip, lr}\n\t");     \
+                                       __isr_##func();                                 \
+                                       asm volatile (                                  \
+                                               "ldmfd sp!, {r0-r3, ip, pc}^\n\t");     \
+                               }                                                       \
+                               static NOINLINE void __isr_##func(void)
                #endif
                #ifndef DECLARE_ISR_CONTEXT_SWITCH
-                       #define DECLARE_ISR_CONTEXT_SWITCH(func) \
-                               void __attribute__((interrupt)) func(void)
+                       #define DECLARE_ISR_CONTEXT_SWITCH(func) DECLARE_ISR(func)
                #endif
                #ifndef ISR_PROTO
-                       #define ISR_PROTO(func) \
-                               void __attribute__((interrupt)) func(void)
+                       #define ISR_PROTO(func) void ISR_FUNC func(void)
                #endif
                #ifndef ISR_PROTO_CONTEXT_SWITCH
-                       #define ISR_PROTO_CONTEXT_SWITCH(func)  \
-                               void __attribute__((interrupt)) func(void)
+                       #define ISR_PROTO_CONTEXT_SWITCH(func) ISR_PROTO(func)
                #endif
 
        #endif /* !__IAR_SYSTEMS_ICC_ */