From 28dbd584fb28c9e64987744c5ecbe232982f0762 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Mon, 2 Feb 2009 03:51:50 +0000 Subject: ARMv6: Optimize interrupt enable/disable with cpsie and cpsid. Section off system-arm.h by ARM_ARCH rather than checking within each implementation. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19905 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/system-arm.h | 241 +++++++++++++++++++++++++-------------- 1 file changed, 157 insertions(+), 84 deletions(-) (limited to 'firmware/target/arm') diff --git a/firmware/target/arm/system-arm.h b/firmware/target/arm/system-arm.h index c383121b46..0608f50a02 100644 --- a/firmware/target/arm/system-arm.h +++ b/firmware/target/arm/system-arm.h @@ -21,29 +21,85 @@ #ifndef SYSTEM_ARM_H #define SYSTEM_ARM_H +/* Common to all ARM_ARCH */ #define nop \ asm volatile ("nop") void __div0(void); -/* This gets too complicated otherwise with all the ARM variation and would - have conflicts with another system-target.h elsewhere so include a - subheader from here. */ +#define IRQ_ENABLED 0x00 +#define IRQ_DISABLED 0x80 +#define IRQ_STATUS 0x80 +#define FIQ_ENABLED 0x00 +#define FIQ_DISABLED 0x40 +#define FIQ_STATUS 0x40 +#define IRQ_FIQ_ENABLED 0x00 +#define IRQ_FIQ_DISABLED 0xc0 +#define IRQ_FIQ_STATUS 0xc0 +#define HIGHEST_IRQ_LEVEL IRQ_DISABLED + +#define set_irq_level(status) \ + set_interrupt_status((status), IRQ_STATUS) +#define set_fiq_status(status) \ + set_interrupt_status((status), FIQ_STATUS) + +#define disable_irq_save() \ + disable_interrupt_save(IRQ_STATUS) +#define disable_fiq_save() \ + disable_interrupt_save(FIQ_STATUS) + +#define restore_irq(cpsr) \ + restore_interrupt(cpsr) +#define restore_fiq(cpsr) \ + restore_interrupt(cpsr) + +#define disable_irq() \ + disable_interrupt(IRQ_STATUS) +#define enable_irq() \ + enable_interrupt(IRQ_STATUS) +#define disable_fiq() \ + disable_interrupt(FIQ_STATUS) +#define enable_fiq() \ + enable_interrupt(FIQ_STATUS) + +/* Core-level interrupt masking */ + +static inline int set_interrupt_status(int status, int mask) +{ + unsigned long cpsr; + int oldstatus; + /* Read the old levels and set the new ones */ + asm volatile ( + "mrs %1, cpsr \n" + "bic %0, %1, %[mask] \n" + "orr %0, %0, %2 \n" + "msr cpsr_c, %0 \n" + : "=&r,r"(cpsr), "=&r,r"(oldstatus) + : "r,i"(status & mask), [mask]"i,i"(mask)); + + return oldstatus; +} +static inline void restore_interrupt(int cpsr) +{ + /* Set cpsr_c from value returned by disable_interrupt_save + * or set_interrupt_status */ + asm volatile ("msr cpsr_c, %0" : : "r"(cpsr)); +} + +/* ARM_ARCH version section for architecture*/ + +#if ARM_ARCH >= 6 static inline uint16_t swap16(uint16_t value) /* result[15..8] = value[ 7..0]; result[ 7..0] = value[15..8]; */ { -#if ARM_ARCH >= 6 uint32_t retval; asm volatile ("revsh %0, %1" /* xxAB */ : "=r"(retval) : "r"((uint32_t)value)); /* xxBA */ return retval; -#else - return (value >> 8) | (value << 8); -#endif } static inline uint32_t swap32(uint32_t value) @@ -54,14 +110,104 @@ static inline uint32_t swap32(uint32_t value) result[ 7.. 0] = value[31..24]; */ { -#if ARM_ARCH >= 6 uint32_t retval; asm volatile ("rev %0, %1" /* ABCD */ : "=r"(retval) : "r"(value)); /* DCBA */ return retval; -#else - uint32_t tmp; +} + +static inline uint32_t swap_odd_even32(uint32_t value) +{ + /* + result[31..24],[15.. 8] = value[23..16],[ 7.. 0] + result[23..16],[ 7.. 0] = value[31..24],[15.. 8] + */ + uint32_t retval; + asm volatile ("rev16 %0, %1" /* ABCD */ + : "=r"(retval) : "r"(value)); /* BADC */ + return retval; +} +static inline void enable_interrupt(int mask) +{ + /* Clear I and/or F disable bit */ + /* mask is expected to be constant and so only relevent branch + * is preserved */ + switch (mask & IRQ_FIQ_STATUS) + { + case IRQ_STATUS: + asm volatile ("cpsie i"); + break; + case FIQ_STATUS: + asm volatile ("cpsie f"); + break; + case IRQ_FIQ_STATUS: + asm volatile ("cpsie if"); + break; + } +} + +static inline void disable_interrupt(int mask) +{ + /* Set I and/or F disable bit */ + /* mask is expected to be constant and so only relevent branch + * is preserved */ + switch (mask & IRQ_FIQ_STATUS) + { + case IRQ_STATUS: + asm volatile ("cpsid i"); + break; + case FIQ_STATUS: + asm volatile ("cpsid f"); + break; + case IRQ_FIQ_STATUS: + asm volatile ("cpsid if"); + break; + } +} + +static inline int disable_interrupt_save(int mask) +{ + /* Set I and/or F disable bit and return old cpsr value */ + int cpsr; + /* mask is expected to be constant and so only relevent branch + * is preserved */ + asm volatile("mrs %0, cpsr" : "=r"(cpsr)); + switch (mask & IRQ_FIQ_STATUS) + { + case IRQ_STATUS: + asm volatile ("cpsid i"); + break; + case FIQ_STATUS: + asm volatile ("cpsid f"); + break; + case IRQ_FIQ_STATUS: + asm volatile ("cpsid if"); + break; + } + return cpsr; +} + +#else /* ARM_ARCH < 6 */ + +static inline uint16_t swap16(uint16_t value) + /* + result[15..8] = value[ 7..0]; + result[ 7..0] = value[15..8]; + */ +{ + return (value >> 8) | (value << 8); +} + +static inline uint32_t swap32(uint32_t value) + /* + result[31..24] = value[ 7.. 0]; + result[23..16] = value[15.. 8]; + result[15.. 8] = value[23..16]; + result[ 7.. 0] = value[31..24]; + */ +{ + uint32_t tmp; asm volatile ( "eor %1, %0, %0, ror #16 \n\t" "bic %1, %1, #0xff0000 \n\t" @@ -70,7 +216,6 @@ static inline uint32_t swap32(uint32_t value) : "+r" (value), "=r" (tmp) ); return value; -#endif } static inline uint32_t swap_odd_even32(uint32_t value) @@ -79,14 +224,7 @@ static inline uint32_t swap_odd_even32(uint32_t value) result[31..24],[15.. 8] = value[23..16],[ 7.. 0] result[23..16],[ 7.. 0] = value[31..24],[15.. 8] */ -#if ARM_ARCH >= 6 - uint32_t retval; - asm volatile ("rev16 %0, %1" /* ABCD */ - : "=r"(retval) : "r"(value)); /* BADC */ - return retval; -#else uint32_t tmp; - asm volatile ( /* ABCD */ "bic %1, %0, #0x00ff00 \n\t" /* AB.D */ "bic %0, %0, #0xff0000 \n\t" /* A.CD */ @@ -95,42 +233,6 @@ static inline uint32_t swap_odd_even32(uint32_t value) : "+r" (value), "=r" (tmp) /* BADC */ ); return value; -#endif -} - -/* Core-level interrupt masking */ - -/* This one returns the old status */ -#define IRQ_ENABLED 0x00 -#define IRQ_DISABLED 0x80 -#define IRQ_STATUS 0x80 -#define FIQ_ENABLED 0x00 -#define FIQ_DISABLED 0x40 -#define FIQ_STATUS 0x40 -#define IRQ_FIQ_ENABLED 0x00 -#define IRQ_FIQ_DISABLED 0xc0 -#define IRQ_FIQ_STATUS 0xc0 -#define HIGHEST_IRQ_LEVEL IRQ_DISABLED - -#define set_irq_level(status) \ - set_interrupt_status((status), IRQ_STATUS) -#define set_fiq_status(status) \ - set_interrupt_status((status), FIQ_STATUS) - -static inline int set_interrupt_status(int status, int mask) -{ - unsigned long cpsr; - int oldstatus; - /* Read the old levels and set the new ones */ - asm volatile ( - "mrs %1, cpsr \n" - "bic %0, %1, %[mask] \n" - "orr %0, %0, %2 \n" - "msr cpsr_c, %0 \n" - : "=&r,r"(cpsr), "=&r,r"(oldstatus) - : "r,i"(status & mask), [mask]"i,i"(mask)); - - return oldstatus; } static inline void enable_interrupt(int mask) @@ -155,18 +257,6 @@ static inline void disable_interrupt(int mask) : "=&r"(tmp) : "i"(mask)); } -#define disable_irq() \ - disable_interrupt(IRQ_STATUS) - -#define enable_irq() \ - enable_interrupt(IRQ_STATUS) - -#define disable_fiq() \ - disable_interrupt(FIQ_STATUS) - -#define enable_fiq() \ - enable_interrupt(FIQ_STATUS) - static inline int disable_interrupt_save(int mask) { /* Set I and/or F disable bit and return old cpsr value */ @@ -180,23 +270,6 @@ static inline int disable_interrupt_save(int mask) return cpsr; } -#define disable_irq_save() \ - disable_interrupt_save(IRQ_STATUS) - -#define disable_fiq_save() \ - disable_interrupt_save(FIQ_STATUS) - -static inline void restore_interrupt(int cpsr) -{ - /* Set cpsr_c from value returned by disable_interrupt_save - * or set_interrupt_status */ - asm volatile ("msr cpsr_c, %0" : : "r"(cpsr)); -} - -#define restore_irq(cpsr) \ - restore_interrupt(cpsr) - -#define restore_fiq(cpsr) \ - restore_interrupt(cpsr) +#endif /* ARM_ARCH */ #endif /* SYSTEM_ARM_H */ -- cgit v1.2.3