|
1 /******************************************************************** |
|
2 * * |
|
3 * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * |
|
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * |
|
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * |
|
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * |
|
7 * * |
|
8 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2010 * |
|
9 * by the Xiph.Org Foundation and contributors http://www.xiph.org/ * |
|
10 * * |
|
11 ******************************************************************** |
|
12 |
|
13 CPU capability detection for ARM processors. |
|
14 |
|
15 function: |
|
16 last mod: $Id: cpu.c 17344 2010-07-21 01:42:18Z tterribe $ |
|
17 |
|
18 ********************************************************************/ |
|
19 |
|
20 #include "armcpu.h" |
|
21 |
|
22 #if !defined(OC_ARM_ASM)|| \ |
|
23 !defined(OC_ARM_ASM_EDSP)&&!defined(OC_ARM_ASM_ARMV6)&& \ |
|
24 !defined(OC_ARM_ASM_NEON) |
|
25 ogg_uint32_t oc_cpu_flags_get(void){ |
|
26 return 0; |
|
27 } |
|
28 |
|
29 #elif defined(_MSC_VER) |
|
30 /*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/ |
|
31 # define WIN32_LEAN_AND_MEAN |
|
32 # define WIN32_EXTRA_LEAN |
|
33 # include <windows.h> |
|
34 |
|
35 ogg_uint32_t oc_cpu_flags_get(void){ |
|
36 ogg_uint32_t flags; |
|
37 flags=0; |
|
38 /*MSVC has no inline __asm support for ARM, but it does let you __emit |
|
39 instructions via their assembled hex code. |
|
40 All of these instructions should be essentially nops.*/ |
|
41 # if defined(OC_ARM_ASM_EDSP) |
|
42 __try{ |
|
43 /*PLD [r13]*/ |
|
44 __emit(0xF5DDF000); |
|
45 flags|=OC_CPU_ARM_EDSP; |
|
46 } |
|
47 __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ |
|
48 /*Ignore exception.*/ |
|
49 } |
|
50 # if defined(OC_ARM_ASM_MEDIA) |
|
51 __try{ |
|
52 /*SHADD8 r3,r3,r3*/ |
|
53 __emit(0xE6333F93); |
|
54 flags|=OC_CPU_ARM_MEDIA; |
|
55 } |
|
56 __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ |
|
57 /*Ignore exception.*/ |
|
58 } |
|
59 # if defined(OC_ARM_ASM_NEON) |
|
60 __try{ |
|
61 /*VORR q0,q0,q0*/ |
|
62 __emit(0xF2200150); |
|
63 flags|=OC_CPU_ARM_NEON; |
|
64 } |
|
65 __except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){ |
|
66 /*Ignore exception.*/ |
|
67 } |
|
68 # endif |
|
69 # endif |
|
70 # endif |
|
71 return flags; |
|
72 } |
|
73 |
|
74 #elif defined(__linux__) |
|
75 # include <stdio.h> |
|
76 # include <stdlib.h> |
|
77 # include <string.h> |
|
78 |
|
79 ogg_uint32_t oc_cpu_flags_get(void){ |
|
80 ogg_uint32_t flags; |
|
81 FILE *fin; |
|
82 flags=0; |
|
83 /*Reading /proc/self/auxv would be easier, but that doesn't work reliably on |
|
84 Android. |
|
85 This also means that detection will fail in Scratchbox.*/ |
|
86 fin=fopen("/proc/cpuinfo","r"); |
|
87 if(fin!=NULL){ |
|
88 /*512 should be enough for anybody (it's even enough for all the flags that |
|
89 x86 has accumulated... so far).*/ |
|
90 char buf[512]; |
|
91 while(fgets(buf,511,fin)!=NULL){ |
|
92 if(memcmp(buf,"Features",8)==0){ |
|
93 char *p; |
|
94 p=strstr(buf," edsp"); |
|
95 if(p!=NULL&&(p[5]==' '||p[5]=='\n'))flags|=OC_CPU_ARM_EDSP; |
|
96 p=strstr(buf," neon"); |
|
97 if(p!=NULL&&(p[5]==' '||p[5]=='\n'))flags|=OC_CPU_ARM_NEON; |
|
98 } |
|
99 if(memcmp(buf,"CPU architecture:",17)==0){ |
|
100 int version; |
|
101 version=atoi(buf+17); |
|
102 if(version>=6)flags|=OC_CPU_ARM_MEDIA; |
|
103 } |
|
104 } |
|
105 fclose(fin); |
|
106 } |
|
107 return flags; |
|
108 } |
|
109 |
|
110 #else |
|
111 /*The feature registers which can tell us what the processor supports are |
|
112 accessible in priveleged modes only, so we can't have a general user-space |
|
113 detection method like on x86.*/ |
|
114 # error "Configured to use ARM asm but no CPU detection method available for " \ |
|
115 "your platform. Reconfigure with --disable-asm (or send patches)." |
|
116 #endif |