18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (C) 2004, 2007  Maciej W. Rozycki
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
58c2ecf20Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
68c2ecf20Sopenharmony_ci * for more details.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#ifndef _ASM_COMPILER_H
98c2ecf20Sopenharmony_ci#define _ASM_COMPILER_H
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/*
128c2ecf20Sopenharmony_ci * With GCC 4.5 onwards we can use __builtin_unreachable to indicate to the
138c2ecf20Sopenharmony_ci * compiler that a particular code path will never be hit. This allows it to be
148c2ecf20Sopenharmony_ci * optimised out of the generated binary.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * Unfortunately at least GCC 4.6.3 through 7.3.0 inclusive suffer from a bug
178c2ecf20Sopenharmony_ci * that can lead to instructions from beyond an unreachable statement being
188c2ecf20Sopenharmony_ci * incorrectly reordered into earlier delay slots if the unreachable statement
198c2ecf20Sopenharmony_ci * is the only content of a case in a switch statement. This can lead to
208c2ecf20Sopenharmony_ci * seemingly random behaviour, such as invalid memory accesses from incorrectly
218c2ecf20Sopenharmony_ci * reordered loads or stores. See this potential GCC fix for details:
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci *   https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00360.html
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * It is unclear whether GCC 8 onwards suffer from the same issue - nothing
268c2ecf20Sopenharmony_ci * relevant is mentioned in GCC 8 release notes and nothing obviously relevant
278c2ecf20Sopenharmony_ci * stands out in GCC commit logs, but these newer GCC versions generate very
288c2ecf20Sopenharmony_ci * different code for the testcase which doesn't exhibit the bug.
298c2ecf20Sopenharmony_ci *
308c2ecf20Sopenharmony_ci * GCC also handles stack allocation suboptimally when calling noreturn
318c2ecf20Sopenharmony_ci * functions or calling __builtin_unreachable():
328c2ecf20Sopenharmony_ci *
338c2ecf20Sopenharmony_ci *   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365
348c2ecf20Sopenharmony_ci *
358c2ecf20Sopenharmony_ci * We work around both of these issues by placing a volatile asm statement,
368c2ecf20Sopenharmony_ci * which GCC is prevented from reordering past, prior to __builtin_unreachable
378c2ecf20Sopenharmony_ci * calls.
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci * The .insn statement is required to ensure that any branches to the
408c2ecf20Sopenharmony_ci * statement, which sadly must be kept due to the asm statement, are known to
418c2ecf20Sopenharmony_ci * be branches to code and satisfy linker requirements for microMIPS kernels.
428c2ecf20Sopenharmony_ci */
438c2ecf20Sopenharmony_ci#undef barrier_before_unreachable
448c2ecf20Sopenharmony_ci#define barrier_before_unreachable() asm volatile(".insn")
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#if !defined(CONFIG_CC_IS_GCC) || \
478c2ecf20Sopenharmony_ci    (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
488c2ecf20Sopenharmony_ci# define GCC_OFF_SMALL_ASM() "ZC"
498c2ecf20Sopenharmony_ci#elif defined(CONFIG_CPU_MICROMIPS)
508c2ecf20Sopenharmony_ci# error "microMIPS compilation unsupported with GCC older than 4.9"
518c2ecf20Sopenharmony_ci#else
528c2ecf20Sopenharmony_ci# define GCC_OFF_SMALL_ASM() "R"
538c2ecf20Sopenharmony_ci#endif
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_MIPSR6
568c2ecf20Sopenharmony_ci#define MIPS_ISA_LEVEL "mips64r6"
578c2ecf20Sopenharmony_ci#define MIPS_ISA_ARCH_LEVEL MIPS_ISA_LEVEL
588c2ecf20Sopenharmony_ci#define MIPS_ISA_LEVEL_RAW mips64r6
598c2ecf20Sopenharmony_ci#define MIPS_ISA_ARCH_LEVEL_RAW MIPS_ISA_LEVEL_RAW
608c2ecf20Sopenharmony_ci#elif defined(CONFIG_CPU_MIPSR5)
618c2ecf20Sopenharmony_ci#define MIPS_ISA_LEVEL "mips64r5"
628c2ecf20Sopenharmony_ci#define MIPS_ISA_ARCH_LEVEL MIPS_ISA_LEVEL
638c2ecf20Sopenharmony_ci#define MIPS_ISA_LEVEL_RAW mips64r5
648c2ecf20Sopenharmony_ci#define MIPS_ISA_ARCH_LEVEL_RAW MIPS_ISA_LEVEL_RAW
658c2ecf20Sopenharmony_ci#else
668c2ecf20Sopenharmony_ci/* MIPS64 is a superset of MIPS32 */
678c2ecf20Sopenharmony_ci#define MIPS_ISA_LEVEL "mips64r2"
688c2ecf20Sopenharmony_ci#define MIPS_ISA_ARCH_LEVEL "arch=r4000"
698c2ecf20Sopenharmony_ci#define MIPS_ISA_LEVEL_RAW mips64r2
708c2ecf20Sopenharmony_ci#define MIPS_ISA_ARCH_LEVEL_RAW MIPS_ISA_LEVEL_RAW
718c2ecf20Sopenharmony_ci#endif /* CONFIG_CPU_MIPSR6 */
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#endif /* _ASM_COMPILER_H */
74