123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /* Copyright (c) 2010 Xiph.Org Foundation
- * Copyright (c) 2013 Parrot */
- /*
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- /* Original code from libtheora modified to suit to Opus */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #ifdef OPUS_HAVE_RTCD
- #include "armcpu.h"
- #include "cpu_support.h"
- #include "os_support.h"
- #include "opus_types.h"
- #include "arch.h"
- #define OPUS_CPU_ARM_V4_FLAG (1<<OPUS_ARCH_ARM_V4)
- #define OPUS_CPU_ARM_EDSP_FLAG (1<<OPUS_ARCH_ARM_EDSP)
- #define OPUS_CPU_ARM_MEDIA_FLAG (1<<OPUS_ARCH_ARM_MEDIA)
- #define OPUS_CPU_ARM_NEON_FLAG (1<<OPUS_ARCH_ARM_NEON)
- #if defined(_MSC_VER)
- /*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/
- # define WIN32_LEAN_AND_MEAN
- # define WIN32_EXTRA_LEAN
- # include <windows.h>
- static OPUS_INLINE opus_uint32 opus_cpu_capabilities(void){
- opus_uint32 flags;
- flags=0;
- /* MSVC has no OPUS_INLINE __asm support for ARM, but it does let you __emit
- * instructions via their assembled hex code.
- * All of these instructions should be essentially nops. */
- # if defined(OPUS_ARM_MAY_HAVE_EDSP) || defined(OPUS_ARM_MAY_HAVE_MEDIA) \
- || defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
- __try{
- /*PLD [r13]*/
- __emit(0xF5DDF000);
- flags|=OPUS_CPU_ARM_EDSP_FLAG;
- }
- __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){
- /*Ignore exception.*/
- }
- # if defined(OPUS_ARM_MAY_HAVE_MEDIA) \
- || defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
- __try{
- /*SHADD8 r3,r3,r3*/
- __emit(0xE6333F93);
- flags|=OPUS_CPU_ARM_MEDIA_FLAG;
- }
- __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){
- /*Ignore exception.*/
- }
- # if defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
- __try{
- /*VORR q0,q0,q0*/
- __emit(0xF2200150);
- flags|=OPUS_CPU_ARM_NEON_FLAG;
- }
- __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){
- /*Ignore exception.*/
- }
- # endif
- # endif
- # endif
- return flags;
- }
- #elif defined(__linux__)
- /* Linux based */
- opus_uint32 opus_cpu_capabilities(void)
- {
- opus_uint32 flags = 0;
- FILE *cpuinfo;
- /* Reading /proc/self/auxv would be easier, but that doesn't work reliably on
- * Android */
- cpuinfo = fopen("/proc/cpuinfo", "r");
- if(cpuinfo != NULL)
- {
- /* 512 should be enough for anybody (it's even enough for all the flags that
- * x86 has accumulated... so far). */
- char buf[512];
- while(fgets(buf, 512, cpuinfo) != NULL)
- {
- # if defined(OPUS_ARM_MAY_HAVE_EDSP) || defined(OPUS_ARM_MAY_HAVE_MEDIA) \
- || defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
- /* Search for edsp and neon flag */
- if(memcmp(buf, "Features", 8) == 0)
- {
- char *p;
- p = strstr(buf, " edsp");
- if(p != NULL && (p[5] == ' ' || p[5] == '\n'))
- flags |= OPUS_CPU_ARM_EDSP_FLAG;
- # if defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
- p = strstr(buf, " neon");
- if(p != NULL && (p[5] == ' ' || p[5] == '\n'))
- flags |= OPUS_CPU_ARM_NEON_FLAG;
- # endif
- }
- # endif
- # if defined(OPUS_ARM_MAY_HAVE_MEDIA) \
- || defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
- /* Search for media capabilities (>= ARMv6) */
- if(memcmp(buf, "CPU architecture:", 17) == 0)
- {
- int version;
- version = atoi(buf+17);
- if(version >= 6)
- flags |= OPUS_CPU_ARM_MEDIA_FLAG;
- }
- # endif
- }
- fclose(cpuinfo);
- }
- return flags;
- }
- #else
- /* The feature registers which can tell us what the processor supports are
- * accessible in priveleged modes only, so we can't have a general user-space
- * detection method like on x86.*/
- # error "Configured to use ARM asm but no CPU detection method available for " \
- "your platform. Reconfigure with --disable-rtcd (or send patches)."
- #endif
- int opus_select_arch(void)
- {
- opus_uint32 flags = opus_cpu_capabilities();
- int arch = 0;
- if(!(flags & OPUS_CPU_ARM_EDSP_FLAG)) {
- /* Asserts ensure arch values are sequential */
- celt_assert(arch == OPUS_ARCH_ARM_V4);
- return arch;
- }
- arch++;
- if(!(flags & OPUS_CPU_ARM_MEDIA_FLAG)) {
- celt_assert(arch == OPUS_ARCH_ARM_EDSP);
- return arch;
- }
- arch++;
- if(!(flags & OPUS_CPU_ARM_NEON_FLAG)) {
- celt_assert(arch == OPUS_ARCH_ARM_MEDIA);
- return arch;
- }
- arch++;
- celt_assert(arch == OPUS_ARCH_ARM_NEON);
- return arch;
- }
- #endif
|