Path: blob/master/thirdparty/libtheora/x86_vc/x86cpu.c
9912 views
/********************************************************************1* *2* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *3* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *4* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *5* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *6* *7* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *8* by the Xiph.Org Foundation and contributors *9* https://www.xiph.org/ *10* *11********************************************************************1213CPU capability detection for x86 processors.14Originally written by Rudolf Marek.1516function:1718********************************************************************/1920#include "x86cpu.h"2122#if !defined(OC_X86_ASM)23ogg_uint32_t oc_cpu_flags_get(void){24return 0;25}26#else27/*Why does MSVC need this complicated rigamarole?28At this point I honestly do not care.*/2930/*Visual C cpuid helper function.31For VS2005 we could as well use the _cpuid builtin, but that wouldn't work32for VS2003 users, so we do it in inline assembler.*/33static void oc_cpuid_helper(ogg_uint32_t _cpu_info[4],ogg_uint32_t _op){34_asm{35mov eax,[_op]36mov esi,_cpu_info37cpuid38mov [esi+0],eax39mov [esi+4],ebx40mov [esi+8],ecx41mov [esi+12],edx42}43}4445# define cpuid(_op,_eax,_ebx,_ecx,_edx) \46do{ \47ogg_uint32_t cpu_info[4]; \48oc_cpuid_helper(cpu_info,_op); \49(_eax)=cpu_info[0]; \50(_ebx)=cpu_info[1]; \51(_ecx)=cpu_info[2]; \52(_edx)=cpu_info[3]; \53}while(0)5455static void oc_detect_cpuid_helper(ogg_uint32_t *_eax,ogg_uint32_t *_ebx){56_asm{57pushfd58pushfd59pop eax60mov ebx,eax61xor eax,200000h62push eax63popfd64pushfd65pop eax66popfd67mov ecx,_eax68mov [ecx],eax69mov ecx,_ebx70mov [ecx],ebx71}72}7374static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){75ogg_uint32_t flags;76/*If there isn't even MMX, give up.*/77if(!(_edx&0x00800000))return 0;78flags=OC_CPU_X86_MMX;79if(_edx&0x02000000)flags|=OC_CPU_X86_MMXEXT|OC_CPU_X86_SSE;80if(_edx&0x04000000)flags|=OC_CPU_X86_SSE2;81if(_ecx&0x00000001)flags|=OC_CPU_X86_PNI;82if(_ecx&0x00000100)flags|=OC_CPU_X86_SSSE3;83if(_ecx&0x00080000)flags|=OC_CPU_X86_SSE4_1;84if(_ecx&0x00100000)flags|=OC_CPU_X86_SSE4_2;85return flags;86}8788static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){89ogg_uint32_t flags;90/*If there isn't even MMX, give up.*/91if(!(_edx&0x00800000))return 0;92flags=OC_CPU_X86_MMX;93if(_edx&0x00400000)flags|=OC_CPU_X86_MMXEXT;94if(_edx&0x80000000)flags|=OC_CPU_X86_3DNOW;95if(_edx&0x40000000)flags|=OC_CPU_X86_3DNOWEXT;96if(_ecx&0x00000040)flags|=OC_CPU_X86_SSE4A;97if(_ecx&0x00000800)flags|=OC_CPU_X86_SSE5;98return flags;99}100101ogg_uint32_t oc_cpu_flags_get(void){102ogg_uint32_t flags;103ogg_uint32_t eax;104ogg_uint32_t ebx;105ogg_uint32_t ecx;106ogg_uint32_t edx;107# if !defined(__amd64__)&&!defined(__x86_64__)108/*Not all x86-32 chips support cpuid, so we have to check.*/109oc_detect_cpuid_helper(&eax,&ebx);110/*No cpuid.*/111if(eax==ebx)return 0;112# endif113cpuid(0,eax,ebx,ecx,edx);114/* l e t n I e n i u n e G*/115if(ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547||116/* 6 8 x M T e n i u n e G*/117ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547){118int family;119int model;120/*Intel, Transmeta (tested with Crusoe TM5800):*/121cpuid(1,eax,ebx,ecx,edx);122flags=oc_parse_intel_flags(edx,ecx);123family=(eax>>8)&0xF;124model=(eax>>4)&0xF;125/*The SSE unit on the Pentium M and Core Duo is much slower than the MMX126unit, so don't use it.*/127if(family==6&&(model==9||model==13||model==14)){128flags&=~(OC_CPU_X86_SSE2|OC_CPU_X86_PNI);129}130}131/* D M A c i t n e h t u A*/132else if(ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541||133/* C S N y b e d o e G*/134ecx==0x43534e20&&edx==0x79622065&&ebx==0x646f6547){135/*AMD, Geode:*/136cpuid(0x80000000,eax,ebx,ecx,edx);137if(eax<0x80000001)flags=0;138else{139cpuid(0x80000001,eax,ebx,ecx,edx);140flags=oc_parse_amd_flags(edx,ecx);141}142/*Also check for SSE.*/143cpuid(1,eax,ebx,ecx,edx);144flags|=oc_parse_intel_flags(edx,ecx);145}146/*Technically some VIA chips can be configured in the BIOS to return any147string here the user wants.148There is a special detection method that can be used to identify such149processors, but in my opinion, if the user really wants to change it, they150deserve what they get.*/151/* s l u a H r u a t n e C*/152else if(ecx==0x736C7561&&edx==0x48727561&&ebx==0x746E6543){153/*VIA:*/154/*I only have documentation for the C7 (Esther) and Isaiah (forthcoming)155chips (thanks to the engineers from Centaur Technology who provided it).156These chips support Intel-like cpuid info.157The C3-2 (Nehemiah) cores appear to, as well.*/158cpuid(1,eax,ebx,ecx,edx);159flags=oc_parse_intel_flags(edx,ecx);160if(eax>=0x80000001){161/*The (non-Nehemiah) C3 processors support AMD-like cpuid info.162We need to check this even if the Intel test succeeds to pick up 3DNow!163support on these processors.164Unlike actual AMD processors, we cannot _rely_ on this info, since165some cores (e.g., the 693 stepping of the Nehemiah) claim to support166this function, yet return edx=0, despite the Intel test indicating167MMX support.168Therefore the features detected here are strictly added to those169detected by the Intel test.*/170/*TODO: How about earlier chips?*/171cpuid(0x80000001,eax,ebx,ecx,edx);172/*Note: As of the C7, this function returns Intel-style extended feature173flags, not AMD-style.174Currently, this only defines bits 11, 20, and 29 (0x20100800), which175do not conflict with any of the AMD flags we inspect.176For the remaining bits, Intel tells us, "Do not count on their value",177but VIA assures us that they will all be zero (at least on the C7 and178Isaiah chips).179In the (unlikely) event a future processor uses bits 18, 19, 30, or 31180(0xC0C00000) for something else, we will have to add code to detect181the model to decide when it is appropriate to inspect them.*/182flags|=oc_parse_amd_flags(edx,ecx);183}184}185else{186/*Implement me.*/187flags=0;188}189return flags;190}191#endif192193194