blob: 009eafa2ea0da4397bf350b2d24ee44d5659320f [file] [log] [blame]
#ifndef __ASM_ARM_COMPILER_H
#define __ASM_ARM_COMPILER_H
/*
* This is used to ensure the compiler did actually allocate the register we
* asked it for some inline assembly sequences. Apparently we can't trust
* the compiler from one version to another so a bit of paranoia won't hurt.
* This string is meant to be concatenated with the inline asm string and
* will cause compilation to stop on mismatch.
* (for details, see gcc PR 15089)
*/
#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
#if defined(CONFIG_SMP) && !defined(CONFIG_CPU_V6)
/*
* Read TPIDRPRW.
* GCC requires a workaround as it does not treat a "memory" clobber on a
* non-volatile asm block as a side-effect.
* We want to allow caching the value, so for GCC avoid using volatile and
* instead use a fake stack read to hazard against barrier().
*/
#if defined(__clang__)
static inline unsigned long read_TPIDRPRW(void)
{
unsigned long off;
/*
* Read TPIDRPRW.
*/
asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) : : "memory");
return off;
}
#else
static inline unsigned long read_TPIDRPRW(void)
{
unsigned long off;
register unsigned long *sp asm ("sp");
asm("mrc p15, 0, %0, c13, c0, 4" : "=r" (off) : "Q" (*sp));
return off;
}
#endif
#endif
#endif /* __ASM_ARM_COMPILER_H */