123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- /*
- * intrinsics.h
- *
- * Compiler intrinsics for ARMv7-M core.
- *
- * Written & released by Keir Fraser <keir.xen@gmail.com>
- *
- * This is free and unencumbered software released into the public domain.
- * See the file COPYING for more details, or visit <http://unlicense.org>.
- */
- struct exception_frame {
- uint32_t r0, r1, r2, r3, r12, lr, pc, psr;
- };
- #define _STR(x) #x
- #define STR(x) _STR(x)
- /* Force a compilation error if condition is true */
- #define BUILD_BUG_ON(cond) ({ _Static_assert(!(cond), "!(" #cond ")"); })
- #define aligned(x) __attribute__((aligned(x)))
- #define packed __attribute((packed))
- #define always_inline __inline__ __attribute__((always_inline))
- #define noinline __attribute__((noinline))
- #define likely(x) __builtin_expect(!!(x),1)
- #define unlikely(x) __builtin_expect(!!(x),0)
- #define unreachable() do { ASSERT(0); __builtin_unreachable(); } while (0)
- #define illegal() asm volatile (".short 0xde00");
- #define barrier() asm volatile ("" ::: "memory")
- #define cpu_sync() asm volatile("dsb; isb" ::: "memory")
- #define cpu_relax() asm volatile ("nop" ::: "memory")
- #define sv_call(imm) asm volatile ( "svc %0" : : "i" (imm) )
- #define read_special(reg) ({ \
- uint32_t __x; \
- asm volatile ("mrs %0,"#reg : "=r" (__x) ::); \
- __x; \
- })
- #define write_special(reg,val) ({ \
- uint32_t __x = (uint32_t)(val); \
- asm volatile ("msr "#reg",%0" :: "r" (__x) :); \
- })
- /* CONTROL[1] == 0 => running on Master Stack (Exception Handler mode). */
- #define CONTROL_SPSEL 2
- #define in_exception() (!(read_special(control) & CONTROL_SPSEL))
- #define global_disable_exceptions() \
- asm volatile ("cpsid f; cpsid i" ::: "memory")
- #define global_enable_exceptions() \
- asm volatile ("cpsie f; cpsie i" ::: "memory")
- /* NB. IRQ disable via CPSID/MSR is self-synchronising. No barrier needed. */
- #define IRQ_global_disable() asm volatile ("cpsid i" ::: "memory")
- #define IRQ_global_enable() asm volatile ("cpsie i" ::: "memory")
- #define IRQ_global_save(flags) ({ \
- (flags) = read_special(primask) & 1; \
- IRQ_global_disable(); })
- #define IRQ_global_restore(flags) ({ \
- if (flags == 0) IRQ_global_enable(); })
- /* Save/restore IRQ priority levels.
- * NB. IRQ disable via MSR is self-synchronising. I have confirmed this on
- * Cortex-M3: any pending IRQs are handled before they are disabled by
- * a BASEPRI update. Hence no barrier is needed here. */
- #define IRQ_save(newpri) ({ \
- uint8_t __newpri = (newpri)<<4; \
- uint8_t __oldpri = read_special(basepri); \
- if (!__oldpri || (__oldpri > __newpri)) \
- write_special(basepri, __newpri); \
- __oldpri; })
- /* NB. Same as CPSIE, any pending IRQ enabled by this BASEPRI update may
- * execute a couple of instructions after the MSR instruction. This has been
- * confirmed on Cortex-M3. */
- #define IRQ_restore(oldpri) write_special(basepri, (oldpri))
- /* Cortex initialisation */
- void cortex_init(void);
- #if defined(CORTEX_M7)
- /* Cache operations */
- void icache_invalidate_all(void);
- void icache_enable(void);
- void dcache_invalidate_all(void);
- void dcache_clear_and_invalidate_all(void);
- void dcache_enable(void);
- void dcache_disable(void);
- #elif defined(CORTEX_M3)
- /* No caches in Cortex M3 */
- #define icache_invalidate_all() ((void)0)
- #define icache_enable() ((void)0)
- #define dcache_invalidate_all() ((void)0)
- #define dcache_clear_and_invalidate_all() ((void)0)
- #define dcache_enable() ((void)0)
- #define dcache_disable() ((void)0)
- #endif
- /*
- * Local variables:
- * mode: C
- * c-file-style: "Linux"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
|