Statistics
| Branch: | Revision:

ffmpeg / libavcodec / x86 / cpuid.c @ b1c32fb5

History | View | Annotate | Download (4.69 KB)

1 04d7f601 Diego Biurrun
/*
2
 * CPU detection code, extracted from mmx.h
3
 * (c)1997-99 by H. Dietz and R. Fisher
4
 * Converted to C and improved by Fabrice Bellard.
5
 *
6 b78e7197 Diego Biurrun
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9 04d7f601 Diego Biurrun
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11 b78e7197 Diego Biurrun
 * version 2.1 of the License, or (at your option) any later version.
12 04d7f601 Diego Biurrun
 *
13 b78e7197 Diego Biurrun
 * FFmpeg is distributed in the hope that it will be useful,
14 04d7f601 Diego Biurrun
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19 b78e7197 Diego Biurrun
 * License along with FFmpeg; if not, write to the Free Software
20 04d7f601 Diego Biurrun
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22 de6d9b64 Fabrice Bellard
23
#include <stdlib.h>
24 245976da Diego Biurrun
#include "libavutil/x86_cpu.h"
25
#include "libavcodec/dsputil.h"
26 de6d9b64 Fabrice Bellard
27 ade6e7f3 Diego Biurrun
#undef printf
28
29 1d20b11a Nick Kurshev
/* ebx saving is necessary for PIC. gcc seems unable to see it alone */
30
#define cpuid(index,eax,ebx,ecx,edx)\
31 be449fca Diego Pettenò
    __asm__ volatile\
32 bb270c08 Diego Biurrun
        ("mov %%"REG_b", %%"REG_S"\n\t"\
33 1d20b11a Nick Kurshev
         "cpuid\n\t"\
34 053dea12 Aurelien Jacobs
         "xchg %%"REG_b", %%"REG_S\
35 1d20b11a Nick Kurshev
         : "=a" (eax), "=S" (ebx),\
36
           "=c" (ecx), "=d" (edx)\
37 c10e9f70 Nick Kurshev
         : "0" (index));
38 de6d9b64 Fabrice Bellard
39
/* Function to test if multimedia instructions are supported...  */
40
int mm_support(void)
41
{
42 e7ddb0cf Matthieu Castet
    int rval = 0;
43 de6d9b64 Fabrice Bellard
    int eax, ebx, ecx, edx;
44 e42a152b Michael Niedermayer
    int max_std_level, max_ext_level, std_caps=0, ext_caps=0;
45 6526976f Ronald S. Bultje
    int family=0, model=0;
46
    union { int i[3]; char c[12]; } vendor;
47 115329f1 Diego Biurrun
48 d05f808d Zuxy Meng
#if ARCH_X86_32
49
    x86_reg a, c;
50 be449fca Diego Pettenò
    __asm__ volatile (
51 80465c7e Diego Biurrun
        /* See if CPUID instruction is supported ... */
52
        /* ... Get copies of EFLAGS into eax and ecx */
53 d05f808d Zuxy Meng
        "pushfl\n\t"
54 80465c7e Diego Biurrun
        "pop %0\n\t"
55
        "mov %0, %1\n\t"
56 115329f1 Diego Biurrun
57 80465c7e Diego Biurrun
        /* ... Toggle the ID bit in one copy and store */
58
        /*     to the EFLAGS reg */
59
        "xor $0x200000, %0\n\t"
60
        "push %0\n\t"
61 d05f808d Zuxy Meng
        "popfl\n\t"
62 115329f1 Diego Biurrun
63 80465c7e Diego Biurrun
        /* ... Get the (hopefully modified) EFLAGS */
64 d05f808d Zuxy Meng
        "pushfl\n\t"
65 80465c7e Diego Biurrun
        "pop %0\n\t"
66
        : "=a" (a), "=c" (c)
67
        :
68
        : "cc"
69
        );
70 115329f1 Diego Biurrun
71 8b4d077f Aurelien Jacobs
    if (a == c)
72 de6d9b64 Fabrice Bellard
        return 0; /* CPUID not supported */
73 d05f808d Zuxy Meng
#endif
74 de6d9b64 Fabrice Bellard
75 6526976f Ronald S. Bultje
    cpuid(0, max_std_level, vendor.i[0], vendor.i[2], vendor.i[1]);
76 e42a152b Michael Niedermayer
77
    if(max_std_level >= 1){
78
        cpuid(1, eax, ebx, ecx, std_caps);
79 6526976f Ronald S. Bultje
        family = ((eax>>8)&0xf) + ((eax>>20)&0xff);
80
        model  = ((eax>>4)&0xf) + ((eax>>12)&0xf0);
81 e42a152b Michael Niedermayer
        if (std_caps & (1<<23))
82 7160bb71 Stefano Sabatini
            rval |= AV_CPU_FLAG_MMX;
83 115329f1 Diego Biurrun
        if (std_caps & (1<<25))
84 7160bb71 Stefano Sabatini
            rval |= AV_CPU_FLAG_MMX2
85 b250f9c6 Aurelien Jacobs
#if HAVE_SSE
86 7160bb71 Stefano Sabatini
                  | AV_CPU_FLAG_SSE;
87 115329f1 Diego Biurrun
        if (std_caps & (1<<26))
88 7160bb71 Stefano Sabatini
            rval |= AV_CPU_FLAG_SSE2;
89 392f6da8 Zuxy Meng
        if (ecx & 1)
90 7160bb71 Stefano Sabatini
            rval |= AV_CPU_FLAG_SSE3;
91 5a5c770d Guillaume Poirier
        if (ecx & 0x00000200 )
92 7160bb71 Stefano Sabatini
            rval |= AV_CPU_FLAG_SSSE3;
93 710441c2 David Conrad
        if (ecx & 0x00080000 )
94 7160bb71 Stefano Sabatini
            rval |= AV_CPU_FLAG_SSE4;
95 710441c2 David Conrad
        if (ecx & 0x00100000 )
96 7160bb71 Stefano Sabatini
            rval |= AV_CPU_FLAG_SSE42;
97 1435e4cc Michael Niedermayer
#endif
98
                  ;
99 e42a152b Michael Niedermayer
    }
100
101
    cpuid(0x80000000, max_ext_level, ebx, ecx, edx);
102
103
    if(max_ext_level >= 0x80000001){
104
        cpuid(0x80000001, eax, ebx, ecx, ext_caps);
105
        if (ext_caps & (1<<31))
106 7160bb71 Stefano Sabatini
            rval |= AV_CPU_FLAG_3DNOW;
107 e42a152b Michael Niedermayer
        if (ext_caps & (1<<30))
108 7160bb71 Stefano Sabatini
            rval |= AV_CPU_FLAG_3DNOWEXT;
109 e42a152b Michael Niedermayer
        if (ext_caps & (1<<23))
110 7160bb71 Stefano Sabatini
            rval |= AV_CPU_FLAG_MMX;
111 392f6da8 Zuxy Meng
        if (ext_caps & (1<<22))
112 7160bb71 Stefano Sabatini
            rval |= AV_CPU_FLAG_MMX2;
113 de6d9b64 Fabrice Bellard
    }
114 392f6da8 Zuxy Meng
115 6526976f Ronald S. Bultje
    if (!strncmp(vendor.c, "GenuineIntel", 12) &&
116
        family == 6 && (model == 9 || model == 13 || model == 14)) {
117
        /* 6/9 (pentium-m "banias"), 6/13 (pentium-m "dothan"), and 6/14 (core1 "yonah")
118
         * theoretically support sse2, but it's usually slower than mmx,
119
         * so let's just pretend they don't. */
120 7160bb71 Stefano Sabatini
        if (rval & AV_CPU_FLAG_SSE2) rval ^= AV_CPU_FLAG_SSE2SLOW|AV_CPU_FLAG_SSE2;
121
        if (rval & AV_CPU_FLAG_SSE3) rval ^= AV_CPU_FLAG_SSE3SLOW|AV_CPU_FLAG_SSE3;
122 6526976f Ronald S. Bultje
    }
123
124 e42a152b Michael Niedermayer
#if 0
125 6526976f Ronald S. Bultje
    av_log(NULL, AV_LOG_DEBUG, "%s%s%s%s%s%s%s%s%s%s%s%s\n",
126 7160bb71 Stefano Sabatini
        (rval&AV_CPU_FLAG_MMX) ? "MMX ":"",
127
        (rval&AV_CPU_FLAG_MMX2) ? "MMX2 ":"",
128
        (rval&AV_CPU_FLAG_SSE) ? "SSE ":"",
129
        (rval&AV_CPU_FLAG_SSE2) ? "SSE2 ":"",
130
        (rval&AV_CPU_FLAG_SSE2SLOW) ? "SSE2(slow) ":"",
131
        (rval&AV_CPU_FLAG_SSE3) ? "SSE3 ":"",
132
        (rval&AV_CPU_FLAG_SSE3SLOW) ? "SSE3(slow) ":"",
133
        (rval&AV_CPU_FLAG_SSSE3) ? "SSSE3 ":"",
134
        (rval&AV_CPU_FLAG_SSE4) ? "SSE4.1 ":"",
135
        (rval&AV_CPU_FLAG_SSE42) ? "SSE4.2 ":"",
136
        (rval&AV_CPU_FLAG_3DNOW) ? "3DNow ":"",
137
        (rval&AV_CPU_FLAG_3DNOWEXT) ? "3DNowExt ":"");
138 e42a152b Michael Niedermayer
#endif
139
    return rval;
140 de6d9b64 Fabrice Bellard
}
141 c10e9f70 Nick Kurshev
142 34933442 Diego Biurrun
#ifdef TEST
143 c10e9f70 Nick Kurshev
int main ( void )
144
{
145 80465c7e Diego Biurrun
    int mm_flags;
146
    mm_flags = mm_support();
147
    printf("mm_support = 0x%08X\n",mm_flags);
148
    return 0;
149 c10e9f70 Nick Kurshev
}
150
#endif