1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * Copyright (C) 2004, 2007 Maciej W. Rozycki 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * This file is subject to the terms and conditions of the GNU General Public 5*4882a593Smuzhiyun * License. See the file "COPYING" in the main directory of this archive 6*4882a593Smuzhiyun * for more details. 7*4882a593Smuzhiyun */ 8*4882a593Smuzhiyun #ifndef _ASM_COMPILER_H 9*4882a593Smuzhiyun #define _ASM_COMPILER_H 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun /* 12*4882a593Smuzhiyun * With GCC 4.5 onwards we can use __builtin_unreachable to indicate to the 13*4882a593Smuzhiyun * compiler that a particular code path will never be hit. This allows it to be 14*4882a593Smuzhiyun * optimised out of the generated binary. 15*4882a593Smuzhiyun * 16*4882a593Smuzhiyun * Unfortunately at least GCC 4.6.3 through 7.3.0 inclusive suffer from a bug 17*4882a593Smuzhiyun * that can lead to instructions from beyond an unreachable statement being 18*4882a593Smuzhiyun * incorrectly reordered into earlier delay slots if the unreachable statement 19*4882a593Smuzhiyun * is the only content of a case in a switch statement. This can lead to 20*4882a593Smuzhiyun * seemingly random behaviour, such as invalid memory accesses from incorrectly 21*4882a593Smuzhiyun * reordered loads or stores. See this potential GCC fix for details: 22*4882a593Smuzhiyun * 23*4882a593Smuzhiyun * https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00360.html 24*4882a593Smuzhiyun * 25*4882a593Smuzhiyun * It is unclear whether GCC 8 onwards suffer from the same issue - nothing 26*4882a593Smuzhiyun * relevant is mentioned in GCC 8 release notes and nothing obviously relevant 27*4882a593Smuzhiyun * stands out in GCC commit logs, but these newer GCC versions generate very 28*4882a593Smuzhiyun * different code for the testcase which doesn't exhibit the bug. 29*4882a593Smuzhiyun * 30*4882a593Smuzhiyun * GCC also handles stack allocation suboptimally when calling noreturn 31*4882a593Smuzhiyun * functions or calling __builtin_unreachable(): 32*4882a593Smuzhiyun * 33*4882a593Smuzhiyun * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365 34*4882a593Smuzhiyun * 35*4882a593Smuzhiyun * We work around both of these issues by placing a volatile asm statement, 36*4882a593Smuzhiyun * which GCC is prevented from reordering past, prior to __builtin_unreachable 37*4882a593Smuzhiyun * calls. 38*4882a593Smuzhiyun * 39*4882a593Smuzhiyun * The .insn statement is required to ensure that any branches to the 40*4882a593Smuzhiyun * statement, which sadly must be kept due to the asm statement, are known to 41*4882a593Smuzhiyun * be branches to code and satisfy linker requirements for microMIPS kernels. 42*4882a593Smuzhiyun */ 43*4882a593Smuzhiyun #undef barrier_before_unreachable 44*4882a593Smuzhiyun #define barrier_before_unreachable() asm volatile(".insn") 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun #if !defined(CONFIG_CC_IS_GCC) || \ 47*4882a593Smuzhiyun (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) 48*4882a593Smuzhiyun # define GCC_OFF_SMALL_ASM() "ZC" 49*4882a593Smuzhiyun #elif defined(CONFIG_CPU_MICROMIPS) 50*4882a593Smuzhiyun # error "microMIPS compilation unsupported with GCC older than 4.9" 51*4882a593Smuzhiyun #else 52*4882a593Smuzhiyun # define GCC_OFF_SMALL_ASM() "R" 53*4882a593Smuzhiyun #endif 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun #ifdef CONFIG_CPU_MIPSR6 56*4882a593Smuzhiyun #define MIPS_ISA_LEVEL "mips64r6" 57*4882a593Smuzhiyun #define MIPS_ISA_ARCH_LEVEL MIPS_ISA_LEVEL 58*4882a593Smuzhiyun #define MIPS_ISA_LEVEL_RAW mips64r6 59*4882a593Smuzhiyun #define MIPS_ISA_ARCH_LEVEL_RAW MIPS_ISA_LEVEL_RAW 60*4882a593Smuzhiyun #elif defined(CONFIG_CPU_MIPSR5) 61*4882a593Smuzhiyun #define MIPS_ISA_LEVEL "mips64r5" 62*4882a593Smuzhiyun #define MIPS_ISA_ARCH_LEVEL MIPS_ISA_LEVEL 63*4882a593Smuzhiyun #define MIPS_ISA_LEVEL_RAW mips64r5 64*4882a593Smuzhiyun #define MIPS_ISA_ARCH_LEVEL_RAW MIPS_ISA_LEVEL_RAW 65*4882a593Smuzhiyun #else 66*4882a593Smuzhiyun /* MIPS64 is a superset of MIPS32 */ 67*4882a593Smuzhiyun #define MIPS_ISA_LEVEL "mips64r2" 68*4882a593Smuzhiyun #define MIPS_ISA_ARCH_LEVEL "arch=r4000" 69*4882a593Smuzhiyun #define MIPS_ISA_LEVEL_RAW mips64r2 70*4882a593Smuzhiyun #define MIPS_ISA_ARCH_LEVEL_RAW MIPS_ISA_LEVEL_RAW 71*4882a593Smuzhiyun #endif /* CONFIG_CPU_MIPSR6 */ 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun #endif /* _ASM_COMPILER_H */ 74