1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
////////////////////////////////////////////////////////////////////////////////
///
/// Generic version of the x86 CPU extension detection routine.
///
/// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp'
/// for the Microsoft compiler version.
///
/// Author : Copyright (c) Olli Parviainen
/// Author e-mail : oparviai 'at' iki.fi
/// SoundTouch WWW: http://www.surina.net/soundtouch
///
////////////////////////////////////////////////////////////////////////////////
//
// Last changed : $Date: 2011-07-16 15:27:51 +0300 (Sat, 16 Jul 2011) $
// File revision : $Revision: 4 $
//
// $Id: cpu_detect_x86_gcc.cpp 123 2011-07-16 12:27:51Z oparviai $
//
////////////////////////////////////////////////////////////////////////////////
//
// License :
//
// SoundTouch audio processing library
// Copyright (c) Olli Parviainen
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
////////////////////////////////////////////////////////////////////////////////
#include <stdexcept>
#include <string>
#include "cpu_detect.h"
#include "STTypes.h"
using namespace std;
#include <stdio.h>
//////////////////////////////////////////////////////////////////////////////
//
// processor instructions extension detection routines
//
//////////////////////////////////////////////////////////////////////////////
// Flag variable indicating whick ISA extensions are disabled (for debugging)
static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions
// Disables given set of instruction extensions. See SUPPORT_... defines.
void disableExtensions(uint dwDisableMask)
{
_dwDisabledISA = dwDisableMask;
}
/// Checks which instruction set extensions are supported by the CPU.
uint detectCPUextensions(void)
{
#if (!(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS) || !(__GNUC__))
return 0; // always disable extensions on non-x86 platforms.
#else
uint res = 0;
if (_dwDisabledISA == 0xffffffff) return 0;
asm volatile(
#ifndef __x86_64__
// Check if 'cpuid' instructions is available by toggling eflags bit 21.
// Skip this for x86-64 as they always have cpuid while stack manipulation
// differs from 16/32bit ISA.
"\n\txor %%esi, %%esi" // clear %%esi = result register
"\n\tpushf" // save eflags to stack
"\n\tmovl (%%esp), %%eax" // load eax from stack (with eflags)
"\n\tmovl %%eax, %%ecx" // save the original eflags values to ecx
"\n\txor $0x00200000, %%eax" // toggle bit 21
"\n\tmovl %%eax, (%%esp)" // store toggled eflags to stack
"\n\tpopf" // load eflags from stack
"\n\tpushf" // save updated eflags to stack
"\n\tmovl (%%esp), %%eax" // load eax from stack
"\n\tpopf" // pop stack to restore esp
"\n\txor %%edx, %%edx" // clear edx for defaulting no mmx
"\n\tcmp %%ecx, %%eax" // compare to original eflags values
"\n\tjz end" // jumps to 'end' if cpuid not present
#endif // __x86_64__
// cpuid instruction available, test for presence of mmx instructions
"\n\tmovl $1, %%eax"
"\n\tcpuid"
"\n\ttest $0x00800000, %%edx"
"\n\tjz end" // branch if MMX not available
"\n\tor $0x01, %%esi" // otherwise add MMX support bit
"\n\ttest $0x02000000, %%edx"
"\n\tjz test3DNow" // branch if SSE not available
"\n\tor $0x08, %%esi" // otherwise add SSE support bit
"\n\ttest3DNow:"
// test for precense of AMD extensions
"\n\tmov $0x80000000, %%eax"
"\n\tcpuid"
"\n\tcmp $0x80000000, %%eax"
"\n\tjbe end" // branch if no AMD extensions detected
// test for precense of 3DNow! extension
"\n\tmov $0x80000001, %%eax"
"\n\tcpuid"
"\n\ttest $0x80000000, %%edx"
"\n\tjz end" // branch if 3DNow! not detected
"\n\tor $0x02, %%esi" // otherwise add 3DNow support bit
"\n\tend:"
"\n\tmov %%esi, %0"
: "=r" (res)
: /* no inputs */
: "%edx", "%eax", "%ecx", "%esi" );
return res & ~_dwDisabledISA;
#endif
}
|