michael@0: michael@0: /* michael@0: * Copyright 2012 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef SkUtilsArm_DEFINED michael@0: #define SkUtilsArm_DEFINED michael@0: michael@0: #include "SkUtils.h" michael@0: michael@0: // Define SK_ARM_NEON_MODE to one of the following values michael@0: // corresponding respectively to: michael@0: // - No ARM Neon support at all (not targetting ARMv7-A, or don't have NEON) michael@0: // - Full ARM Neon support (i.e. assume the CPU always supports it) michael@0: // - Optional ARM Neon support (i.e. probe CPU at runtime) michael@0: // michael@0: #define SK_ARM_NEON_MODE_NONE 0 michael@0: #define SK_ARM_NEON_MODE_ALWAYS 1 michael@0: #define SK_ARM_NEON_MODE_DYNAMIC 2 michael@0: michael@0: #if defined(SK_CPU_ARM) && defined(__ARM_HAVE_OPTIONAL_NEON_SUPPORT) michael@0: # define SK_ARM_NEON_MODE SK_ARM_NEON_MODE_DYNAMIC michael@0: #elif defined(SK_CPU_ARM) && defined(__ARM_HAVE_NEON) michael@0: # define SK_ARM_NEON_MODE SK_ARM_NEON_MODE_ALWAYS michael@0: #else michael@0: # define SK_ARM_NEON_MODE SK_ARM_NEON_MODE_NONE michael@0: #endif michael@0: michael@0: // Convenience test macros, always defined as 0 or 1 michael@0: #define SK_ARM_NEON_IS_NONE (SK_ARM_NEON_MODE == SK_ARM_NEON_MODE_NONE) michael@0: #define SK_ARM_NEON_IS_ALWAYS (SK_ARM_NEON_MODE == SK_ARM_NEON_MODE_ALWAYS) michael@0: #define SK_ARM_NEON_IS_DYNAMIC (SK_ARM_NEON_MODE == SK_ARM_NEON_MODE_DYNAMIC) michael@0: michael@0: // The sk_cpu_arm_has_neon() function returns true iff the target device michael@0: // is ARMv7-A and supports Neon instructions. In DYNAMIC mode, this actually michael@0: // probes the CPU at runtime (and caches the result). michael@0: michael@0: #if SK_ARM_NEON_IS_NONE michael@0: static inline bool sk_cpu_arm_has_neon(void) { michael@0: return false; michael@0: } michael@0: #elif SK_ARM_NEON_IS_ALWAYS michael@0: static inline bool sk_cpu_arm_has_neon(void) { michael@0: return true; michael@0: } michael@0: #else // SK_ARM_NEON_IS_DYNAMIC michael@0: michael@0: extern bool sk_cpu_arm_has_neon(void) SK_PURE_FUNC; michael@0: #endif michael@0: michael@0: // Use SK_ARM_NEON_WRAP(symbol) to map 'symbol' to a NEON-specific symbol michael@0: // when applicable. This will transform 'symbol' differently depending on michael@0: // the current NEON configuration, i.e.: michael@0: // michael@0: // NONE -> 'symbol' michael@0: // ALWAYS -> 'symbol_neon' michael@0: // DYNAMIC -> 'symbol' or 'symbol_neon' depending on runtime check. michael@0: // michael@0: // The goal is to simplify user code, for example: michael@0: // michael@0: // return SK_ARM_NEON_WRAP(do_something)(params); michael@0: // michael@0: // Replaces the equivalent: michael@0: // michael@0: // #if SK_ARM_NEON_IS_NONE michael@0: // return do_something(params); michael@0: // #elif SK_ARM_NEON_IS_ALWAYS michael@0: // return do_something_neon(params); michael@0: // #elif SK_ARM_NEON_IS_DYNAMIC michael@0: // if (sk_cpu_arm_has_neon()) michael@0: // return do_something_neon(params); michael@0: // else michael@0: // return do_something(params); michael@0: // #endif michael@0: // michael@0: #if SK_ARM_NEON_IS_NONE michael@0: # define SK_ARM_NEON_WRAP(x) (x) michael@0: #elif SK_ARM_NEON_IS_ALWAYS michael@0: # define SK_ARM_NEON_WRAP(x) (x ## _neon) michael@0: #elif SK_ARM_NEON_IS_DYNAMIC michael@0: # define SK_ARM_NEON_WRAP(x) (sk_cpu_arm_has_neon() ? x ## _neon : x) michael@0: #endif michael@0: michael@0: #endif // SkUtilsArm_DEFINED