From 04c9894d563f531a7a04d35de775184b628e105b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 18 Nov 2003 01:27:06 +0000 Subject: [PATCH] Added SDL_HasMMX(), SDL_Has3DNow(), SDL_HasSSE() in SDL_cpuinfo.h --- WhatsNew | 3 + configure.in | 3 + include/Makefile.am | 1 + include/SDL_cpuinfo.h | 58 ++++ src/audio/SDL_mixer.c | 23 +- src/cpuinfo/COPYING.LIB | 438 +++++++++++++++++++++++ src/cpuinfo/Makefile.am | 34 ++ src/cpuinfo/README | 5 + src/cpuinfo/SDL_cpuinfo.c | 96 +++++ src/cpuinfo/_cpuinfo.asm | 611 ++++++++++++++++++++++++++++++++ src/cpuinfo/_pcihelp.asm | 339 ++++++++++++++++++ src/cpuinfo/cpuinfo.h | 203 +++++++++++ src/cpuinfo/gcpuinfo.c | 436 +++++++++++++++++++++++ src/cpuinfo/scitech.mac | 714 ++++++++++++++++++++++++++++++++++++++ src/video/SDL_RLEaccel.c | 17 +- src/video/SDL_blit.c | 18 +- src/video/SDL_blit_A.c | 23 +- src/video/SDL_blit_N.c | 22 +- src/video/SDL_yuv_sw.c | 37 +- 19 files changed, 2977 insertions(+), 104 deletions(-) create mode 100644 include/SDL_cpuinfo.h create mode 100644 src/cpuinfo/COPYING.LIB create mode 100644 src/cpuinfo/Makefile.am create mode 100644 src/cpuinfo/README create mode 100644 src/cpuinfo/SDL_cpuinfo.c create mode 100644 src/cpuinfo/_cpuinfo.asm create mode 100644 src/cpuinfo/_pcihelp.asm create mode 100644 src/cpuinfo/cpuinfo.h create mode 100644 src/cpuinfo/gcpuinfo.c create mode 100644 src/cpuinfo/scitech.mac diff --git a/WhatsNew b/WhatsNew index 6caef02c1..0c3e8095d 100644 --- a/WhatsNew +++ b/WhatsNew @@ -3,6 +3,9 @@ This is a list of API changes in SDL's version history. Version 1.0: +1.2.7: + Added SDL_HasMMX(), SDL_Has3DNow(), SDL_HasSSE() + 1.2.6: Added SDL_LoadObject(), SDL_LoadFunction(), and SDL_UnloadObject() diff --git a/configure.in b/configure.in index 3c9df87ad..c019a4892 100644 --- a/configure.in +++ b/configure.in @@ -503,6 +503,7 @@ CheckNASM() CFLAGS="$CFLAGS -I\$(top_srcdir)/src/hermes" SDL_EXTRADIRS="$SDL_EXTRADIRS hermes" SDL_EXTRALIBS="$SDL_EXTRALIBS hermes/libhermes.la" + use_nasm=yes fi fi } @@ -2569,6 +2570,7 @@ AM_CONDITIONAL(TARGET_MINT, test $ARCH = mint) # More automake conditionals AM_CONDITIONAL(USE_DIRECTX, test x$use_directx = xyes) AM_CONDITIONAL(USE_CLONE, test x$use_clone = xyes) +AM_CONDITIONAL(HAVE_NASM, test x$use_nasm = xyes) # Set conditional variables for shared and static library selection. # These are not used in any Makefile.am but in sdl-config.in. @@ -2774,6 +2776,7 @@ src/thread/Makefile src/timer/Makefile src/endian/Makefile src/file/Makefile +src/cpuinfo/Makefile src/hermes/Makefile sdl-config SDL.spec diff --git a/include/Makefile.am b/include/Makefile.am index 639fc3fc9..3fce37e87 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -11,6 +11,7 @@ libSDLinclude_HEADERS = \ SDL_byteorder.h \ SDL_cdrom.h \ SDL_copying.h \ + SDL_cpuinfo.h \ SDL_endian.h \ SDL_error.h \ SDL_events.h \ diff --git a/include/SDL_cpuinfo.h b/include/SDL_cpuinfo.h new file mode 100644 index 000000000..81d586b9d --- /dev/null +++ b/include/SDL_cpuinfo.h @@ -0,0 +1,58 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id$"; +#endif + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* CPU feature detection for SDL */ + +#ifndef _SDL_cpuinfo_h +#define _SDL_cpuinfo_h + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* This function returns true if the CPU has MMX features + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX(); + +/* This function returns true if the CPU has 3DNow features + */ +extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNow(); + +/* This function returns true if the CPU has SSE features + */ +extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE(); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* _SDL_cpuinfo_h */ diff --git a/src/audio/SDL_mixer.c b/src/audio/SDL_mixer.c index 4ab6ca3c1..126ef9146 100644 --- a/src/audio/SDL_mixer.c +++ b/src/audio/SDL_mixer.c @@ -34,28 +34,13 @@ static char rcsid = #include "SDL_audio.h" #include "SDL_mutex.h" #include "SDL_timer.h" +#include "SDL_cpuinfo.h" #include "SDL_sysaudio.h" +#include "SDL_cpuinfo.h" #include "SDL_mixer_MMX.h" #include "SDL_mixer_MMX_VC.h" #include "SDL_mixer_m68k.h" -/* Function to check the CPU flags */ -#define MMX_CPU 0x800000 -#ifdef USE_ASMBLIT -#define CPU_Flags() Hermes_X86_CPU() -#else -#define CPU_Flags() 0L -#endif - -#ifdef USE_ASMBLIT -#define X86_ASSEMBLER -#define HermesConverterInterface void -#define HermesClearInterface void -#define STACKCALL - -#include "HeadX86.h" -#endif - /* This table is used to add two sound values together and pin * the value to avoid overflow. (used with permission from ARDI) * Changed to use 0xFE instead of 0xFF for better sound quality. @@ -154,7 +139,7 @@ void SDL_MixAudio (Uint8 *dst, const Uint8 *src, Uint32 len, int volume) case AUDIO_S8: { #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) - if (CPU_Flags() & MMX_CPU) + if (SDL_HasMMX()) { SDL_MixAudio_MMX_S8((char*)dst,(char*)src,(unsigned int)len,(int)volume); } @@ -201,7 +186,7 @@ void SDL_MixAudio (Uint8 *dst, const Uint8 *src, Uint32 len, int volume) case AUDIO_S16LSB: { #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) - if (CPU_Flags() & MMX_CPU) + if (SDL_HasMMX()) { SDL_MixAudio_MMX_S16((char*)dst,(char*)src,(unsigned int)len,(int)volume); } diff --git a/src/cpuinfo/COPYING.LIB b/src/cpuinfo/COPYING.LIB new file mode 100644 index 000000000..69679a563 --- /dev/null +++ b/src/cpuinfo/COPYING.LIB @@ -0,0 +1,438 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + diff --git a/src/cpuinfo/Makefile.am b/src/cpuinfo/Makefile.am new file mode 100644 index 000000000..db3ff1820 --- /dev/null +++ b/src/cpuinfo/Makefile.am @@ -0,0 +1,34 @@ +########################################################################### +# +# Some consistent rules for building asm files: + +STRIP_FPIC = sh $(top_srcdir)/strip_fPIC.sh + +SUFFIXES = .asm + +.asm.lo: + $(LIBTOOL) --tag=CC --mode=compile $(STRIP_FPIC) $(NASM) -t -D __FLAT__ -D __NOU__ @NASMFLAGS@ $< -o $*.o + +########################################################################### + +# The cpuinfo library target +noinst_LTLIBRARIES = libcpuinfo.la + +if HAVE_NASM +ARCH_SRCS = \ + gcpuinfo.c \ + _cpuinfo.asm \ + _pcihelp.asm +else +ARCH_SRCS = +endif + +COMMON_SRCS = \ + SDL_cpuinfo.c + +libcpuinfo_la_SOURCES = $(ARCH_SRCS) $(COMMON_SRCS) + +EXTRA_DIST = \ + COPYING.LIB \ + README + diff --git a/src/cpuinfo/README b/src/cpuinfo/README new file mode 100644 index 000000000..a5d59fa84 --- /dev/null +++ b/src/cpuinfo/README @@ -0,0 +1,5 @@ +This is a stripped down version of the portable CPU detection code included +in the SciTech SNAP Graphics SDK. It is redistributed under the LGPL license, +which can be found in COPYING.LIB. + +You can visit SciTech Software Inc. at: http://www.scitechsoft.com/ diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c new file mode 100644 index 000000000..9490b787d --- /dev/null +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -0,0 +1,96 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id$"; +#endif + +/* CPU feature detection for SDL */ + +#include "SDL.h" +//#include "SDL_cpuinfo.h" + +#define CPU_HAS_MMX 0x00000001 +#define CPU_HAS_3DNOW 0x00000002 +#define CPU_HAS_SSE 0x00000004 + +/* These functions come from SciTech's PM library */ +extern int CPU_haveMMX(); +extern int CPU_have3DNow(); +extern int CPU_haveSSE(); + +static Uint32 SDL_CPUFeatures = 0xFFFFFFFF; + +static Uint32 SDL_GetCPUFeatures() +{ + if ( SDL_CPUFeatures == 0xFFFFFFFF ) { + SDL_CPUFeatures = 0; + if ( CPU_haveMMX() ) { + SDL_CPUFeatures |= CPU_HAS_MMX; + } + if ( CPU_have3DNow() ) { + SDL_CPUFeatures |= CPU_HAS_3DNOW; + } + if ( CPU_haveSSE() ) { + SDL_CPUFeatures |= CPU_HAS_SSE; + } + } + return SDL_CPUFeatures; +} + +SDL_bool SDL_HasMMX() +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_MMX ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +SDL_bool SDL_Has3DNow() +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOW ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +SDL_bool SDL_HasSSE() +{ + if ( SDL_GetCPUFeatures() & CPU_HAS_SSE ) { + return SDL_TRUE; + } + return SDL_FALSE; +} + +#ifdef TEST_MAIN + +#include + +int main() +{ + printf("MMX: %d\n", SDL_HasMMX()); + printf("3DNow: %d\n", SDL_Has3DNow()); + printf("SSE: %d\n", SDL_HasSSE()); +} + +#endif /* TEST_MAIN */ diff --git a/src/cpuinfo/_cpuinfo.asm b/src/cpuinfo/_cpuinfo.asm new file mode 100644 index 000000000..d16ba5b73 --- /dev/null +++ b/src/cpuinfo/_cpuinfo.asm @@ -0,0 +1,611 @@ +;**************************************************************************** +;* +;* SciTech OS Portability Manager Library +;* +;* ======================================================================== +;* +;* Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved. +;* +;* This file may be distributed and/or modified under the terms of the +;* GNU Lesser General Public License version 2.1 as published by the Free +;* Software Foundation and appearing in the file LICENSE.LGPL included +;* in the packaging of this file. +;* +;* Licensees holding a valid Commercial License for this product from +;* SciTech Software, Inc. may use this file in accordance with the +;* Commercial License Agreement provided with the Software. +;* +;* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +;* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;* PURPOSE. +;* +;* See http://www.scitechsoft.com/license/ for information about +;* the licensing options available and how to purchase a Commercial +;* License Agreement. +;* +;* Contact license@scitechsoft.com if any conditions of this licensing +;* are not clear to you, or you have questions about licensing options. +;* +;* ======================================================================== +;* +;* Language: NASM +;* Environment: Intel 32 bit Protected Mode. +;* +;* Description: Code to determine the Intel processor type. +;* +;**************************************************************************** + +include "scitech.mac" + +header _cpuinfo + +begdataseg _cpuinfo ; Start of data segment + +cache_id db "01234567890123456" +intel_id db "GenuineIntel" ; Intel vendor ID +cyrix_id db "CyrixInstead" ; Cyrix vendor ID +amd_id db "AuthenticAMD" ; AMD vendor ID +idt_id db "CentaurHauls" ; IDT vendor ID + +CPU_IDT EQU 01000h ; Flag for IDT processors +CPU_Cyrix EQU 02000h ; Flag for Cyrix processors +CPU_AMD EQU 04000h ; Flag for AMD processors +CPU_Intel EQU 08000h ; Flag for Intel processors + +enddataseg _cpuinfo + +begcodeseg _cpuinfo ; Start of code segment + +%macro mCPU_ID 0 +db 00Fh,0A2h +%endmacro + +%macro mRDTSC 0 +db 00Fh,031h +%endmacro + +;---------------------------------------------------------------------------- +; bool _CPU_check80386(void) +;---------------------------------------------------------------------------- +; Determines if we have an i386 processor. +;---------------------------------------------------------------------------- +cprocstart _CPU_check80386 + + enter_c + + xor edx,edx ; EDX = 0, not an 80386 + mov bx, sp + and sp, ~3 + pushfd ; Push original EFLAGS + pop eax ; Get original EFLAGS + mov ecx, eax ; Save original EFLAGS + xor eax, 40000h ; Flip AC bit in EFLAGS + push eax ; Save new EFLAGS value on + ; stack + popfd ; Replace current EFLAGS value + pushfd ; Get new EFLAGS + pop eax ; Store new EFLAGS in EAX + xor eax, ecx ; Can't toggle AC bit, + ; processor=80386 + jnz @@Done ; Jump if not an 80386 processor + inc edx ; We have an 80386 + +@@Done: push ecx + popfd + mov sp, bx + mov eax, edx + leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; bool _CPU_check80486(void) +;---------------------------------------------------------------------------- +; Determines if we have an i486 processor. +;---------------------------------------------------------------------------- +cprocstart _CPU_check80486 + + enter_c + +; Distinguish between the i486 and Pentium by the ability to set the ID flag +; in the EFLAGS register. If the ID flag is set, then we can use the CPUID +; instruction to determine the final version of the chip. Otherwise we +; simply have an 80486. + +; Distinguish between the i486 and Pentium by the ability to set the ID flag +; in the EFLAGS register. If the ID flag is set, then we can use the CPUID +; instruction to determine the final version of the chip. Otherwise we +; simply have an 80486. + + pushfd ; Get original EFLAGS + pop eax + mov ecx, eax + xor eax, 200000h ; Flip ID bit in EFLAGS + push eax ; Save new EFLAGS value on stack + popfd ; Replace current EFLAGS value + pushfd ; Get new EFLAGS + pop eax ; Store new EFLAGS in EAX + xor eax, ecx ; Can not toggle ID bit, + jnz @@1 ; Processor=80486 + mov eax,1 ; We dont have a Pentium + jmp @@Done +@@1: mov eax,0 ; We have Pentium or later +@@Done: leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; bool _CPU_checkClone(void) +;---------------------------------------------------------------------------- +; Checks if the i386 or i486 processor is a clone or genuine Intel. +;---------------------------------------------------------------------------- +cprocstart _CPU_checkClone + + enter_c + + mov ax,5555h ; Check to make sure this is a 32-bit processor + xor dx,dx + mov cx,2h + div cx ; Perform Division + clc + jnz @@NoClone + jmp @@Clone +@@NoClone: + stc +@@Clone: + pushfd + pop eax ; Get the flags + and eax,1 + xor eax,1 ; EAX=0 is probably Intel, EAX=1 is a Clone + + leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; bool _CPU_haveCPUID(void) +;---------------------------------------------------------------------------- +; Determines if we have support for the CPUID instruction. +;---------------------------------------------------------------------------- +cprocstart _CPU_haveCPUID + + enter_c + +ifdef flatmodel + pushfd ; Get original EFLAGS + pop eax + mov ecx, eax + xor eax, 200000h ; Flip ID bit in EFLAGS + push eax ; Save new EFLAGS value on stack + popfd ; Replace current EFLAGS value + pushfd ; Get new EFLAGS + pop eax ; Store new EFLAGS in EAX + xor eax, ecx ; Can not toggle ID bit, + jnz @@1 ; Processor=80486 + mov eax,0 ; We dont have CPUID support + jmp @@Done +@@1: mov eax,1 ; We have CPUID support +else + mov eax,0 ; CPUID requires 32-bit pmode +endif +@@Done: leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; uint _CPU_checkCPUID(void) +;---------------------------------------------------------------------------- +; Determines the CPU type using the CPUID instruction. +;---------------------------------------------------------------------------- +cprocstart _CPU_checkCPUID + + enter_c + + xor eax, eax ; Set up for CPUID instruction + mCPU_ID ; Get and save vendor ID + cmp eax, 1 ; Make sure 1 is valid input for CPUID + jl @@Fail ; We dont have the CPUID instruction + xor eax,eax ; Assume vendor is unknown + +; Check for GenuineIntel processors + + LEA_L esi,intel_id + cmp [DWORD esi], ebx + jne @@NotIntel + cmp [DWORD esi+4], edx + jne @@NotIntel + cmp [DWORD esi+8], ecx + jne @@NotIntel + mov eax,CPU_Intel ; Flag that we have GenuineIntel + jmp @@FoundVendor + +; Check for CyrixInstead processors + +@@NotIntel: + LEA_L esi,cyrix_id + cmp [DWORD esi], ebx + jne @@NotCyrix + cmp [DWORD esi+4], edx + jne @@NotCyrix + cmp [DWORD esi+8], ecx + jne @@NotCyrix + mov eax,CPU_Cyrix ; Flag that we have CyrixInstead + jmp @@FoundVendor + +; Check for AuthenticAMD processors + +@@NotCyrix: + LEA_L esi,amd_id + cmp [DWORD esi], ebx + jne @@NotAMD + cmp [DWORD esi+4], edx + jne @@NotAMD + cmp [DWORD esi+8], ecx + jne @@NotAMD + mov eax,CPU_AMD ; Flag that we have AuthenticAMD + jmp @@FoundVendor + +; Check for CentaurHauls processors + +@@NotAMD: + LEA_L esi,idt_id + cmp [DWORD esi], ebx + jne @@NotIDT + cmp [DWORD esi+4], edx + jne @@NotIDT + cmp [DWORD esi+8], ecx + jne @@NotIDT + mov eax,CPU_IDT ; Flag that we have AuthenticIDT + jmp @@FoundVendor + +@@NotIDT: + +@@FoundVendor: + push eax + xor eax, eax + inc eax + mCPU_ID ; Get family/model/stepping/features + and eax, 0F00h + shr eax, 8 ; Isolate CPU family + and eax, 0Fh + cmp eax, 0Fh ; Check for Pentium 4 which is an 0Fh! + jne @@NotP4 + mov eax, 07h ; Change P4 ID to 7 for consistency +@@NotP4: + pop ecx + or eax,ecx ; Combine in the CPU vendor flag +@@Done: leave_c + ret + +@@Fail: xor eax,eax + jmp @@Done + +cprocend + +;---------------------------------------------------------------------------- +; uint _CPU_getCPUIDModel(void) +;---------------------------------------------------------------------------- +; Determines the CPU type using the CPUID instruction. +;---------------------------------------------------------------------------- +cprocstart _CPU_getCPUIDModel + + enter_c + + xor eax, eax ; Set up for CPUID instruction + mCPU_ID ; Get and save vendor ID + cmp eax, 1 ; Make sure 1 is valid input for CPUID + jl @@Fail ; We dont have the CPUID instruction + xor eax, eax + inc eax + mCPU_ID ; Get family/model/stepping/features + and eax, 0F0h + shr eax, 4 ; Isolate model +@@Done: leave_c + ret + +@@Fail: xor eax,eax + jmp @@Done + +cprocend + +;---------------------------------------------------------------------------- +; uint _CPU_getCPUIDStepping(void) +;---------------------------------------------------------------------------- +; Determines the CPU type using the CPUID instruction. +;---------------------------------------------------------------------------- +cprocstart _CPU_getCPUIDStepping + + enter_c + + xor eax, eax ; Set up for CPUID instruction + mCPU_ID ; Get and save vendor ID + cmp eax, 1 ; Make sure 1 is valid input for CPUID + jl @@Fail ; We dont have the CPUID instruction + xor eax, eax + inc eax + mCPU_ID ; Get family/model/stepping/features + and eax, 00Fh ; Isolate stepping +@@Done: leave_c + ret + +@@Fail: xor eax,eax + jmp @@Done + +cprocend + +;---------------------------------------------------------------------------- +; uint _CPU_getCPUIDFeatures(void) +;---------------------------------------------------------------------------- +; Determines the CPU type using the CPUID instruction. +;---------------------------------------------------------------------------- +cprocstart _CPU_getCPUIDFeatures + + enter_c + + xor eax, eax ; Set up for CPUID instruction + mCPU_ID ; Get and save vendor ID + cmp eax, 1 ; Make sure 1 is valid input for CPUID + jl @@Fail ; We dont have the CPUID instruction + xor eax, eax + inc eax + mCPU_ID ; Get family/model/stepping/features + mov eax, edx +@@Done: leave_c + ret + +@@Fail: xor eax,eax + jmp @@Done + +cprocend + +;---------------------------------------------------------------------------- +; uint _CPU_getCacheSize(void) +;---------------------------------------------------------------------------- +; Determines the CPU cache size for Intel processors +;---------------------------------------------------------------------------- +cprocstart _CPU_getCacheSize + + enter_c + xor eax, eax ; Set up for CPUID instruction + mCPU_ID ; Get and save vendor ID + cmp eax,2 ; Make sure 2 is valid input for CPUID + jl @@Fail ; We dont have the CPUID instruction + mov eax,2 + mCPU_ID ; Get cache descriptors + LEA_L esi,cache_id ; Get address of cache ID (-fPIC aware) + shr eax,8 + mov [esi+0],eax + mov [esi+3],ebx + mov [esi+7],ecx + mov [esi+11],edx + xor eax,eax + LEA_L esi,cache_id ; Get address of cache ID (-fPIC aware) + mov edi,15 +@@ScanLoop: + cmp [BYTE esi],41h + mov eax,128 + je @@Done + cmp [BYTE esi],42h + mov eax,256 + je @@Done + cmp [BYTE esi],43h + mov eax,512 + je @@Done + cmp [BYTE esi],44h + mov eax,1024 + je @@Done + cmp [BYTE esi],45h + mov eax,2048 + je @@Done + inc esi + dec edi + jnz @@ScanLoop + +@@Done: leave_c + ret + +@@Fail: xor eax,eax + jmp @@Done + +cprocend + +;---------------------------------------------------------------------------- +; uint _CPU_have3DNow(void) +;---------------------------------------------------------------------------- +; Determines the CPU type using the CPUID instruction. +;---------------------------------------------------------------------------- +cprocstart _CPU_have3DNow + + enter_c + + mov eax,80000000h ; Query for extended functions + mCPU_ID ; Get extended function limit + cmp eax,80000001h + jbe @@Fail ; Nope, we dont have function 800000001h + mov eax,80000001h ; Setup extended function 800000001h + mCPU_ID ; and get the information + test edx,80000000h ; Bit 31 is set if 3DNow! present + jz @@Fail ; Nope, we dont have 3DNow support + mov eax,1 ; Yep, we have 3DNow! support! +@@Done: leave_c + ret + +@@Fail: xor eax,eax + jmp @@Done + +cprocend + +;---------------------------------------------------------------------------- +; ulong _CPU_quickRDTSC(void) +;---------------------------------------------------------------------------- +; Reads the time stamp counter and returns the low order 32-bits +;---------------------------------------------------------------------------- +cprocstart _CPU_quickRDTSC + + mRDTSC + ret + +cprocend + +;---------------------------------------------------------------------------- +; void _CPU_runBSFLoop(ulong interations) +;---------------------------------------------------------------------------- +; Runs a loop of BSF instructions for the specified number of iterations +;---------------------------------------------------------------------------- +cprocstart _CPU_runBSFLoop + + ARG iterations:ULONG + + push _bp + mov _bp,_sp + push _bx + + mov edx,[iterations] + mov eax,80000000h + mov ebx,edx + + ALIGN 4 + +@@loop: bsf ecx,eax + dec ebx + jnz @@loop + + pop _bx + pop _bp + ret + +cprocend + +;---------------------------------------------------------------------------- +; void _CPU_readTimeStamp(CPU_largeInteger *time); +;---------------------------------------------------------------------------- +; Reads the time stamp counter and returns the 64-bit result. +;---------------------------------------------------------------------------- +cprocstart _CPU_readTimeStamp + + mRDTSC + mov ecx,[esp+4] ; Access directly without stack frame + mov [ecx],eax + mov [ecx+4],edx + ret + +cprocend + +;---------------------------------------------------------------------------- +; ulong _CPU_diffTime64(CPU_largeInteger *t1,CPU_largeInteger *t2,CPU_largeInteger *t) +;---------------------------------------------------------------------------- +; Computes the difference between two 64-bit numbers. +;---------------------------------------------------------------------------- +cprocstart _CPU_diffTime64 + + ARG t1:DPTR, t2:DPTR, t:DPTR + + enter_c + + mov ecx,[t2] + mov eax,[ecx] ; EAX := t2.low + mov ecx,[t1] + sub eax,[ecx] + mov edx,eax ; EDX := low difference + mov ecx,[t2] + mov eax,[ecx+4] ; ECX := t2.high + mov ecx,[t1] + sbb eax,[ecx+4] ; EAX := high difference + + mov ebx,[t] ; Store the result + mov [ebx],edx ; Store low part + mov [ebx+4],eax ; Store high part + mov eax,edx ; Return low part +ifndef flatmodel + shld edx,eax,16 ; Return in DX:AX +endif + leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; ulong _CPU_calcMicroSec(CPU_largeInteger *count,ulong freq); +;---------------------------------------------------------------------------- +; Computes the value in microseconds for the elapsed time with maximum +; precision. The formula we use is: +; +; us = (((diff * 0x100000) / freq) * 1000000) / 0x100000) +; +; The power of two multiple before the first divide allows us to scale the +; 64-bit difference using simple shifts, and then the divide brings the +; final result into the range to fit into a 32-bit integer. +;---------------------------------------------------------------------------- +cprocstart _CPU_calcMicroSec + + ARG count:DPTR, freq:ULONG + + enter_c + + mov ecx,[count] + mov eax,[ecx] ; EAX := low part + mov edx,[ecx+4] ; EDX := high part + shld edx,eax,20 + shl eax,20 ; diff * 0x100000 + div [DWORD freq] ; (diff * 0x100000) / freq + mov ecx,1000000 + xor edx,edx + mul ecx ; ((diff * 0x100000) / freq) * 1000000) + shrd eax,edx,20 ; ((diff * 0x100000) / freq) * 1000000) / 0x100000 +ifndef flatmodel + shld edx,eax,16 ; Return in DX:AX +endif + leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; ulong _CPU_mulDiv(ulong a,ulong b,ulong c); +;---------------------------------------------------------------------------- +; Computes the following with 64-bit integer precision: +; +; result = (a * b) / c +; +;---------------------------------------------------------------------------- +cprocstart _CPU_mulDiv + + ARG a:ULONG, b:ULONG, c:ULONG + + enter_c + mov eax,[a] + imul [ULONG b] + idiv [ULONG c] +ifndef flatmodel + shld edx,eax,16 ; Return in DX:AX +endif + leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; int PM_getIOPL(void) +;---------------------------------------------------------------------------- +; Returns current IOPL, callable from any ring, any OS, any day of the week +; (as long as it's 386 compatible). Sort of CPU information too. +;---------------------------------------------------------------------------- +cprocstart PM_getIOPL + + pushfd + pop eax + and eax,0011000000000000b + shr eax,12 + ret + +cprocend + + +endcodeseg _cpuinfo + + END + diff --git a/src/cpuinfo/_pcihelp.asm b/src/cpuinfo/_pcihelp.asm new file mode 100644 index 000000000..0e3b493f2 --- /dev/null +++ b/src/cpuinfo/_pcihelp.asm @@ -0,0 +1,339 @@ +;**************************************************************************** +;* +;* SciTech OS Portability Manager Library +;* +;* ======================================================================== +;* +;* Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved. +;* +;* This file may be distributed and/or modified under the terms of the +;* GNU Lesser General Public License version 2.1 as published by the Free +;* Software Foundation and appearing in the file LICENSE.LGPL included +;* in the packaging of this file. +;* +;* Licensees holding a valid Commercial License for this product from +;* SciTech Software, Inc. may use this file in accordance with the +;* Commercial License Agreement provided with the Software. +;* +;* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +;* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;* PURPOSE. +;* +;* See http://www.scitechsoft.com/license/ for information about +;* the licensing options available and how to purchase a Commercial +;* License Agreement. +;* +;* Contact license@scitechsoft.com if any conditions of this licensing +;* are not clear to you, or you have questions about licensing options. +;* +;* ======================================================================== +;* +;* Language: NASM +;* Environment: Any +;* +;* Description: Helper assembler functions for PCI access module. +;* +;**************************************************************************** + +include "scitech.mac" ; Memory model macros + +header _pcilib + +begcodeseg _pcilib + +ifdef flatmodel + +;---------------------------------------------------------------------------- +; uchar _ASMAPI _BIOS32_service( +; ulong service, +; ulong func, +; ulong *physBase, +; ulong *length, +; ulong *serviceOffset, +; PCIBIOS_entry entry); +;---------------------------------------------------------------------------- +; Call the BIOS32 services directory +;---------------------------------------------------------------------------- +cprocstart _BIOS32_service + + ARG service:ULONG, func:ULONG, physBase:DPTR, len:DPTR, off:DPTR, entry:QWORD + + enter_c + mov eax,[service] + mov ebx,[func] + call far dword [entry] + mov esi,[physBase] + mov [esi],ebx + mov esi,[len] + mov [esi],ecx + mov esi,[off] + mov [esi],edx + leave_c + ret + +cprocend + +endif + +;---------------------------------------------------------------------------- +; ushort _ASMAPI _PCIBIOS_isPresent(ulong i_eax,ulong *o_edx,ushort *oeax, +; uchar *o_cl,PCIBIOS_entry entry) +;---------------------------------------------------------------------------- +; Call the PCI BIOS to determine if it is present. +;---------------------------------------------------------------------------- +cprocstart _PCIBIOS_isPresent + + ARG i_eax:ULONG, o_edx:DPTR, oeax:DPTR, o_cl:DPTR, entry:QWORD + + enter_c + mov eax,[i_eax] +ifdef flatmodel + call far dword [entry] +else + int 1Ah +endif + _les _si,[o_edx] + mov [_ES _si],edx + _les _si,[oeax] + mov [_ES _si],ax + _les _si,[o_cl] + mov [_ES _si],cl + mov ax,bx + leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; ulong _PCIBIOS_service(ulong r_eax,ulong r_ebx,ulong r_edi,ulong r_ecx, +; PCIBIOS_entry entry) +;---------------------------------------------------------------------------- +; Call the PCI BIOS services, either via the 32-bit protected mode entry +; point or via the Int 1Ah 16-bit interrupt. +;---------------------------------------------------------------------------- +cprocstart _PCIBIOS_service + + ARG r_eax:ULONG, r_ebx:ULONG, r_edi:ULONG, r_ecx:ULONG, entry:QWORD + + enter_c + mov eax,[r_eax] + mov ebx,[r_ebx] + mov edi,[r_edi] + mov ecx,[r_ecx] +ifdef flatmodel + call far dword [entry] +else + int 1Ah +endif + mov eax,ecx +ifndef flatmodel + shld edx,eax,16 ; Return result in DX:AX +endif + leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; int _PCIBIOS_getRouting(PCIRoutingOptionsBuffer *buf,PCIBIOS_entry entry); +;---------------------------------------------------------------------------- +; Get the routing options for PCI devices +;---------------------------------------------------------------------------- +cprocstart _PCIBIOS_getRouting + + ARG buf:DPTR, entry:QWORD + + enter_c + mov eax,0B10Eh + mov bx,0 + _les _di,[buf] +ifdef flatmodel + call far dword [entry] +else + int 1Ah +endif + movzx eax,ah + leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; ibool _PCIBIOS_setIRQ(int busDev,int intPin,int IRQ,PCIBIOS_entry entry); +;---------------------------------------------------------------------------- +; Change the IRQ routing for the PCI device +;---------------------------------------------------------------------------- +cprocstart _PCIBIOS_setIRQ + + ARG busDev:UINT, intPin:UINT, IRQ:UINT, entry:QWORD + + enter_c + mov eax,0B10Fh + mov bx,[USHORT busDev] + mov cl,[BYTE intPin] + mov ch,[BYTE IRQ] +ifdef flatmodel + call far dword [entry] +else + int 1Ah +endif + mov eax,1 + jnc @@1 + xor eax,eax ; Function failed! +@@1: leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; ulong _PCIBIOS_specialCycle(int bus,ulong data,PCIBIOS_entry entry); +;---------------------------------------------------------------------------- +; Generate a special cycle via the PCI BIOS. +;---------------------------------------------------------------------------- +cprocstart _PCIBIOS_specialCycle + + ARG bus:UINT, data:ULONG, entry:QWORD + + enter_c + mov eax,0B106h + mov bh,[BYTE bus] + mov ecx,[data] +ifdef flatmodel + call far dword [entry] +else + int 1Ah +endif + leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; ushort _PCI_getCS(void) +;---------------------------------------------------------------------------- +cprocstart _PCI_getCS + + mov ax,cs + ret + +cprocend + +;---------------------------------------------------------------------------- +; int PM_inpb(int port) +;---------------------------------------------------------------------------- +; Reads a byte from the specified port +;---------------------------------------------------------------------------- +cprocstart PM_inpb + + ARG port:UINT + + push _bp + mov _bp,_sp + xor _ax,_ax + mov _dx,[port] + in al,dx + pop _bp + ret + +cprocend + +;---------------------------------------------------------------------------- +; int PM_inpw(int port) +;---------------------------------------------------------------------------- +; Reads a word from the specified port +;---------------------------------------------------------------------------- +cprocstart PM_inpw + + ARG port:UINT + + push _bp + mov _bp,_sp + xor _ax,_ax + mov _dx,[port] + in ax,dx + pop _bp + ret + +cprocend + +;---------------------------------------------------------------------------- +; ulong PM_inpd(int port) +;---------------------------------------------------------------------------- +; Reads a word from the specified port +;---------------------------------------------------------------------------- +cprocstart PM_inpd + + ARG port:UINT + + push _bp + mov _bp,_sp + mov _dx,[port] + in eax,dx +ifndef flatmodel + shld edx,eax,16 ; DX:AX = result +endif + pop _bp + ret + +cprocend + +;---------------------------------------------------------------------------- +; void PM_outpb(int port,int value) +;---------------------------------------------------------------------------- +; Write a byte to the specified port. +;---------------------------------------------------------------------------- +cprocstart PM_outpb + + ARG port:UINT, value:UINT + + push _bp + mov _bp,_sp + mov _dx,[port] + mov _ax,[value] + out dx,al + pop _bp + ret + +cprocend + +;---------------------------------------------------------------------------- +; void PM_outpw(int port,int value) +;---------------------------------------------------------------------------- +; Write a word to the specified port. +;---------------------------------------------------------------------------- +cprocstart PM_outpw + + ARG port:UINT, value:UINT + + push _bp + mov _bp,_sp + mov _dx,[port] + mov _ax,[value] + out dx,ax + pop _bp + ret + +cprocend + +;---------------------------------------------------------------------------- +; void PM_outpd(int port,ulong value) +;---------------------------------------------------------------------------- +; Write a word to the specified port. +;---------------------------------------------------------------------------- +cprocstart PM_outpd + + ARG port:UINT, value:ULONG + + push _bp + mov _bp,_sp + mov _dx,[port] + mov eax,[value] + out dx,eax + pop _bp + ret + +cprocend + +endcodeseg _pcilib + + END diff --git a/src/cpuinfo/cpuinfo.h b/src/cpuinfo/cpuinfo.h new file mode 100644 index 000000000..d0db9d9ea --- /dev/null +++ b/src/cpuinfo/cpuinfo.h @@ -0,0 +1,203 @@ +/**************************************************************************** +* +* SciTech OS Portability Manager Library +* +* ======================================================================== +* +* Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved. +* +* This file may be distributed and/or modified under the terms of the +* GNU Lesser General Public License version 2.1 as published by the Free +* Software Foundation and appearing in the file LICENSE.LGPL included +* in the packaging of this file. +* +* Licensees holding a valid Commercial License for this product from +* SciTech Software, Inc. may use this file in accordance with the +* Commercial License Agreement provided with the Software. +* +* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +* PURPOSE. +* +* See http://www.scitechsoft.com/license/ for information about +* the licensing options available and how to purchase a Commercial +* License Agreement. +* +* Contact license@scitechsoft.com if any conditions of this licensing +* are not clear to you, or you have questions about licensing options. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* +* Description: Header file for PM library functions for querying the CPU +* type, CPU speed and CPU features. Includes support for +* high precision timing on Pentium based systems using the +* Read Time Stamp Counter. +* +****************************************************************************/ + +#ifndef __CPUINFO_H +#define __CPUINFO_H + +//#include "scitech.h" +#include "SDL.h" +#ifdef USE_ASMBLIT +#define __INTEL__ +#endif +typedef enum { + false, + true +} ibool; +typedef Uint8 uchar; +typedef Uint16 ushort; +typedef Uint32 uint; +typedef Uint32 ulong; +typedef Uint64 u64; +#define _ASMAPI SDLCALL + +/*--------------------- Macros and type definitions -----------------------*/ + +/* Define the calling conventions - C always */ + +#define ZAPI _ASMAPI + +/**************************************************************************** +REMARKS: +Defines the types of processors returned by CPU_getProcessorType. + +HEADER: +cpuinfo.h + +MEMBERS: +CPU_i386 - Intel 80386 processor +CPU_i486 - Intel 80486 processor +CPU_Pentium - Intel Pentium(R) processor +CPU_PentiumPro - Intel PentiumPro(R) processor +CPU_PentiumII - Intel PentiumII(R) processor +CPU_Celeron - Intel Celeron(R) processor +CPU_PentiumIII - Intel PentiumIII(R) processor +CPU_Pentium4 - Intel Pentium4(R) processor +CPU_UnkIntel - Unknown Intel processor +CPU_Cyrix6x86 - Cyrix 6x86 processor +CPU_Cyrix6x86MX - Cyrix 6x86MX processor +CPU_CyrixMediaGX - Cyrix MediaGX processor +CPU_CyrixMediaGXm - Cyrix MediaGXm processor +CPU_UnkCyrix - Unknown Cyrix processor +CPU_AMDAm486 - AMD Am486 processor +CPU_AMDAm5x86 - AMD Am5x86 processor +CPU_AMDK5 - AMD K5 processor +CPU_AMDK6 - AMD K6 processor +CPU_AMDK6_2 - AMD K6-2 processor +CPU_AMDK6_2plus - AMD K6-2+ processor +CPU_AMDK6_III - AMD K6-III processor +CPU_AMDK6_IIIplus - AMD K6-III+ processor +CPU_AMDAthlon - AMD Athlon processor +CPU_AMDDuron - AMD Duron processor +CPU_UnkAMD - Unknown AMD processor +CPU_WinChipC6 - IDT WinChip C6 processor +CPU_WinChip2 - IDT WinChip 2 processor +CPU_UnkIDT - Unknown IDT processor +CPU_ViaCyrixIII - Via Cyrix III +CPU_UnkVIA - Unknown Via processor +CPU_Alpha - DEC Alpha processor +CPU_Mips - MIPS processor +CPU_PowerPC - PowerPC processor +CPU_mask - Mask to remove flags and get CPU type +CPU_IDT - This bit is set if the processor vendor is IDT +CPU_Cyrix - This bit is set if the processor vendor is Cyrix +CPU_AMD - This bit is set if the processor vendor is AMD +CPU_Intel - This bit is set if the processor vendor is Intel +CPU_VIA - This bit is set if the processor vendor is Via +CPU_familyMask - Mask to isolate CPU family +CPU_steppingMask - Mask to isolate CPU stepping +CPU_steppingShift - Shift factor for CPU stepping +****************************************************************************/ +typedef enum { + CPU_i386 = 0, + CPU_i486 = 1, + CPU_Pentium = 2, + CPU_PentiumPro = 3, + CPU_PentiumII = 4, + CPU_Celeron = 5, + CPU_PentiumIII = 6, + CPU_Pentium4 = 7, + CPU_UnkIntel = 8, + CPU_Cyrix6x86 = 100, + CPU_Cyrix6x86MX = 101, + CPU_CyrixMediaGX = 102, + CPU_CyrixMediaGXm = 104, + CPU_UnkCyrix = 105, + CPU_AMDAm486 = 200, + CPU_AMDAm5x86 = 201, + CPU_AMDK5 = 202, + CPU_AMDK6 = 203, + CPU_AMDK6_2 = 204, + CPU_AMDK6_2plus = 205, + CPU_AMDK6_III = 206, + CPU_AMDK6_IIIplus = 207, + CPU_UnkAMD = 208, + CPU_AMDAthlon = 250, + CPU_AMDDuron = 251, + CPU_WinChipC6 = 300, + CPU_WinChip2 = 301, + CPU_UnkIDT = 302, + CPU_ViaCyrixIII = 400, + CPU_UnkVIA = 401, + CPU_Alpha = 500, + CPU_Mips = 600, + CPU_PowerPC = 700, + CPU_mask = 0x00000FFF, + CPU_IDT = 0x00001000, + CPU_Cyrix = 0x00002000, + CPU_AMD = 0x00004000, + CPU_Intel = 0x00008000, + CPU_VIA = 0x00010000, + CPU_familyMask = 0x00FFF000, + CPU_steppingMask = 0x0F000000, + CPU_steppingShift = 24 + } CPU_processorType; + +#pragma pack(1) +/**************************************************************************** +REMARKS: +Defines the structure for holding 64-bit integers used for storing the values +returned by the Intel RDTSC instruction. + +HEADER: +cpuinfo.h + +MEMBERS: +low - Low 32-bits of the 64-bit integer +high - High 32-bits of the 64-bit integer +****************************************************************************/ +typedef struct { + ulong low; + ulong high; + } CPU_largeInteger; +#pragma pack() + +/*-------------------------- Function Prototypes --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + +/* Routines to obtain CPU information */ + +uint ZAPI CPU_getProcessorType(void); +ibool ZAPI CPU_haveMMX(void); +ibool ZAPI CPU_have3DNow(void); +ibool ZAPI CPU_haveSSE(void); +ibool ZAPI CPU_haveRDTSC(void); +ulong ZAPI CPU_getProcessorSpeed(ibool accurate); +void ZAPI CPU_getProcessorSpeedInHZ(ibool accurate,CPU_largeInteger *speed); +char * ZAPI CPU_getProcessorName(void); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif + +#endif /* __CPUINFO_H */ + diff --git a/src/cpuinfo/gcpuinfo.c b/src/cpuinfo/gcpuinfo.c new file mode 100644 index 000000000..84776a611 --- /dev/null +++ b/src/cpuinfo/gcpuinfo.c @@ -0,0 +1,436 @@ +/**************************************************************************** +* +* SciTech OS Portability Manager Library +* +* ======================================================================== +* +* Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved. +* +* This file may be distributed and/or modified under the terms of the +* GNU Lesser General Public License version 2.1 as published by the Free +* Software Foundation and appearing in the file LICENSE.LGPL included +* in the packaging of this file. +* +* Licensees holding a valid Commercial License for this product from +* SciTech Software, Inc. may use this file in accordance with the +* Commercial License Agreement provided with the Software. +* +* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +* PURPOSE. +* +* See http://www.scitechsoft.com/license/ for information about +* the licensing options available and how to purchase a Commercial +* License Agreement. +* +* Contact license@scitechsoft.com if any conditions of this licensing +* are not clear to you, or you have questions about licensing options. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* +* Description: Main module to implement the Zen Timer support functions. +* +****************************************************************************/ + +#include "cpuinfo.h" +//#include "pmapi.h" +//#include "oshdr.h" + +/*----------------------------- Implementation ----------------------------*/ + +/* External Intel assembler functions */ +#ifdef __INTEL__ +/* {secret} */ +ibool _ASMAPI _CPU_haveCPUID(void); +/* {secret} */ +ibool _ASMAPI _CPU_check80386(void); +/* {secret} */ +ibool _ASMAPI _CPU_check80486(void); +/* {secret} */ +uint _ASMAPI _CPU_checkCPUID(void); +/* {secret} */ +uint _ASMAPI _CPU_getCPUIDModel(void); +/* {secret} */ +uint _ASMAPI _CPU_getCPUIDStepping(void); +/* {secret} */ +uint _ASMAPI _CPU_getCPUIDFeatures(void); +/* {secret} */ +uint _ASMAPI _CPU_getCacheSize(void); +/* {secret} */ +uint _ASMAPI _CPU_have3DNow(void); +/* {secret} */ +ibool _ASMAPI _CPU_checkClone(void); +/* {secret} */ +void _ASMAPI _CPU_readTimeStamp(CPU_largeInteger *time); +/* {secret} */ +void _ASMAPI _CPU_runBSFLoop(ulong iterations); +/* {secret} */ +ulong _ASMAPI _CPU_mulDiv(ulong a,ulong b,ulong c); +/* {secret} */ +#define CPU_HaveMMX 0x00800000 +#define CPU_HaveRDTSC 0x00000010 +#define CPU_HaveSSE 0x02000000 +#endif + +/*------------------------ Public interface routines ----------------------*/ + +#ifdef __INTEL__ +extern Uint8 PM_inpb(int port); +extern void PM_outpb(int port,Uint8 val); + +/**************************************************************************** +REMARKS: +Read an I/O port location. +****************************************************************************/ +static uchar rdinx( + int port, + int index) +{ + PM_outpb(port,(uchar)index); + return PM_inpb(port+1); +} + +/**************************************************************************** +REMARKS: +Write an I/O port location. +****************************************************************************/ +static void wrinx( + ushort port, + ushort index, + ushort value) +{ + PM_outpb(port,(uchar)index); + PM_outpb(port+1,(uchar)value); +} + +/**************************************************************************** +REMARKS: +Enables the Cyrix CPUID instruction to properly detect MediaGX and 6x86 +processors. +****************************************************************************/ +static void _CPU_enableCyrixCPUID(void) +{ + uchar ccr3; + + //PM_init(); + ccr3 = rdinx(0x22,0xC3); + wrinx(0x22,0xC3,(uchar)(ccr3 | 0x10)); + wrinx(0x22,0xE8,(uchar)(rdinx(0x22,0xE8) | 0x80)); + wrinx(0x22,0xC3,ccr3); +} +#endif + +/**************************************************************************** +DESCRIPTION: +Returns the type of processor in the system. + +HEADER: +cpuinfo.h + +RETURNS: +Numerical identifier for the installed processor + +REMARKS: +Returns the type of processor in the system. Note that if the CPU is an +unknown Pentium family processor that we don't have an enumeration for, +the return value will be greater than or equal to the value of CPU_UnkPentium +(depending on the value returned by the CPUID instruction). + +SEE ALSO: +CPU_getProcessorSpeed, CPU_haveMMX, CPU_getProcessorName +****************************************************************************/ +uint ZAPI CPU_getProcessorType(void) +{ +#if defined(__INTEL__) + uint cpu,vendor,model,cacheSize; + static ibool firstTime = true; + + if (_CPU_haveCPUID()) { + cpu = _CPU_checkCPUID(); + vendor = cpu & ~CPU_mask; + if (vendor == CPU_Intel) { + /* Check for Intel processors */ + switch (cpu & CPU_mask) { + case 4: cpu = CPU_i486; break; + case 5: cpu = CPU_Pentium; break; + case 6: + if ((model = _CPU_getCPUIDModel()) == 1) + cpu = CPU_PentiumPro; + else if (model <= 6) { + cacheSize = _CPU_getCacheSize(); + if ((model == 5 && cacheSize == 0) || + (model == 5 && cacheSize == 256) || + (model == 6 && cacheSize == 128)) + cpu = CPU_Celeron; + else + cpu = CPU_PentiumII; + } + else if (model >= 7) { + /* Model 7 == Pentium III */ + /* Model 8 == Celeron/Pentium III Coppermine */ + cacheSize = _CPU_getCacheSize(); + if ((model == 8 && cacheSize == 128)) + cpu = CPU_Celeron; + else + cpu = CPU_PentiumIII; + } + break; + case 7: + cpu = CPU_Pentium4; + break; + default: + cpu = CPU_UnkIntel; + break; + } + } + else if (vendor == CPU_Cyrix) { + /* Check for Cyrix processors */ + switch (cpu & CPU_mask) { + case 4: + if ((model = _CPU_getCPUIDModel()) == 4) + cpu = CPU_CyrixMediaGX; + else + cpu = CPU_UnkCyrix; + break; + case 5: + if ((model = _CPU_getCPUIDModel()) == 2) + cpu = CPU_Cyrix6x86; + else if (model == 4) + cpu = CPU_CyrixMediaGXm; + else + cpu = CPU_UnkCyrix; + break; + case 6: + if ((model = _CPU_getCPUIDModel()) <= 1) + cpu = CPU_Cyrix6x86MX; + else + cpu = CPU_UnkCyrix; + break; + default: + cpu = CPU_UnkCyrix; + break; + } + } + else if (vendor == CPU_AMD) { + /* Check for AMD processors */ + switch (cpu & CPU_mask) { + case 4: + if ((model = _CPU_getCPUIDModel()) == 0) + cpu = CPU_AMDAm5x86; + else + cpu = CPU_AMDAm486; + break; + case 5: + if ((model = _CPU_getCPUIDModel()) <= 3) + cpu = CPU_AMDK5; + else if (model <= 7) + cpu = CPU_AMDK6; + else if (model == 8) + cpu = CPU_AMDK6_2; + else if (model == 9) + cpu = CPU_AMDK6_III; + else if (model == 13) { + if (_CPU_getCPUIDStepping() <= 3) + cpu = CPU_AMDK6_IIIplus; + else + cpu = CPU_AMDK6_2plus; + } + else + cpu = CPU_UnkAMD; + break; + case 6: + if ((model = _CPU_getCPUIDModel()) == 3) + cpu = CPU_AMDDuron; + else + cpu = CPU_AMDAthlon; + break; + default: + cpu = CPU_UnkAMD; + break; + } + } + else if (vendor == CPU_IDT) { + /* Check for IDT WinChip processors */ + switch (cpu & CPU_mask) { + case 5: + if ((model = _CPU_getCPUIDModel()) <= 4) + cpu = CPU_WinChipC6; + else if (model == 8) + cpu = CPU_WinChip2; + else + cpu = CPU_UnkIDT; + break; + case 6: + vendor = CPU_VIA; + if ((model = _CPU_getCPUIDModel()) <= 6) + cpu = CPU_ViaCyrixIII; + else + cpu = CPU_UnkVIA; + break; + default: + vendor = CPU_VIA; + cpu = CPU_UnkVIA; + break; + } + } + else { + /* Assume a Pentium compatible Intel clone */ + cpu = CPU_Pentium; + } + return cpu | vendor | (_CPU_getCPUIDStepping() << CPU_steppingShift); + } + else { + if (_CPU_check80386()) + cpu = CPU_i386; + else if (_CPU_check80486()) { + /* If we get here we may have a Cyrix processor so we can try + * enabling the CPUID instruction and trying again. + */ + if (firstTime) { + firstTime = false; + _CPU_enableCyrixCPUID(); + return CPU_getProcessorType(); + } + cpu = CPU_i486; + } + else + cpu = CPU_Pentium; + if (!_CPU_checkClone()) + return cpu | CPU_Intel; + return cpu; + } +#elif defined(__ALPHA__) + return CPU_Alpha; +#elif defined(__MIPS__) + return CPU_Mips; +#elif defined(__PPC__) + return CPU_PowerPC; +#endif +} + +/**************************************************************************** +DESCRIPTION: +Returns true if the processor supports Intel MMX extensions. + +HEADER: +cpuinfo.h + +RETURNS: +True if MMX is available, false if not. + +REMARKS: +This function determines if the processor supports the Intel MMX extended +instruction set. + +SEE ALSO: +CPU_getProcessorType, CPU_getProcessorSpeed, CPU_have3DNow, CPU_haveSSE, +CPU_getProcessorName +****************************************************************************/ +ibool ZAPI CPU_haveMMX(void) +{ +#ifdef __INTEL__ + if (_CPU_haveCPUID()) + return (_CPU_getCPUIDFeatures() & CPU_HaveMMX) != 0; + return false; +#else + return false; +#endif +} + +/**************************************************************************** +DESCRIPTION: +Returns true if the processor supports AMD 3DNow! extensions. + +HEADER: +cpuinfo.h + +RETURNS: +True if 3DNow! is available, false if not. + +REMARKS: +This function determines if the processor supports the AMD 3DNow! extended +instruction set. + +SEE ALSO: +CPU_getProcessorType, CPU_getProcessorSpeed, CPU_haveMMX, CPU_haveSSE, +CPU_getProcessorName +****************************************************************************/ +ibool ZAPI CPU_have3DNow(void) +{ +#ifdef __INTEL__ + if (_CPU_haveCPUID()) + return _CPU_have3DNow(); + return false; +#else + return false; +#endif +} + +/**************************************************************************** +DESCRIPTION: +Returns true if the processor supports Intel SSE extensions. + +HEADER: +cpuinfo.h + +RETURNS: +True if Intel SSE is available, false if not. + +REMARKS: +This function determines if the processor supports the Intel SSE extended +instruction set. + +SEE ALSO: +CPU_getProcessorType, CPU_getProcessorSpeed, CPU_haveMMX, CPU_have3DNow, +CPU_getProcessorName +****************************************************************************/ +ibool ZAPI CPU_haveSSE(void) +{ +#ifdef __INTEL__ + if (_CPU_haveCPUID()) + return (_CPU_getCPUIDFeatures() & CPU_HaveSSE) != 0; + return false; +#else + return false; +#endif +} + +/**************************************************************************** +RETURNS: +True if the RTSC instruction is available, false if not. + +REMARKS: +This function determines if the processor supports the Intel RDTSC +instruction, for high precision timing. If the processor is not an Intel or +Intel clone CPU, this function will always return false. + +DESCRIPTION: +Returns true if the processor supports RDTSC extensions. + +HEADER: +cpuinfo.h + +RETURNS: +True if RTSC is available, false if not. + +REMARKS: +This function determines if the processor supports the RDTSC instruction +for reading the processor time stamp counter. + +SEE ALSO: +CPU_getProcessorType, CPU_getProcessorSpeed, CPU_haveMMX, CPU_have3DNow, +CPU_getProcessorName +****************************************************************************/ +ibool ZAPI CPU_haveRDTSC(void) +{ +#ifdef __INTEL__ + if (_CPU_haveCPUID()) + return (_CPU_getCPUIDFeatures() & CPU_HaveRDTSC) != 0; + return false; +#else + return false; +#endif +} diff --git a/src/cpuinfo/scitech.mac b/src/cpuinfo/scitech.mac new file mode 100644 index 000000000..31a1bc764 --- /dev/null +++ b/src/cpuinfo/scitech.mac @@ -0,0 +1,714 @@ +;**************************************************************************** +;* +;* ======================================================================== +;* +;* Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved. +;* +;* This file may be distributed and/or modified under the terms of the +;* GNU Lesser General Public License version 2.1 as published by the Free +;* Software Foundation and appearing in the file LICENSE.LGPL included +;* in the packaging of this file. +;* +;* Licensees holding a valid Commercial License for this product from +;* SciTech Software, Inc. may use this file in accordance with the +;* Commercial License Agreement provided with the Software. +;* +;* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING +;* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +;* PURPOSE. +;* +;* See http://www.scitechsoft.com/license/ for information about +;* the licensing options available and how to purchase a Commercial +;* License Agreement. +;* +;* Contact license@scitechsoft.com if any conditions of this licensing +;* are not clear to you, or you have questions about licensing options. +;* +;* ======================================================================== +;* +;* Language: NetWide Assembler (NASM) +;* Environment: Any Intel IA32 Environment +;* +;* Description: Macros to provide memory model independant assembly language +;* module for C programming. Supports the large and flat memory +;* models. +;* +;* The defines that you should use when assembling modules that +;* use this macro package are: +;* +;* __FLAT__ Assemble for 32-bit FLAT memory model +;* __NOU__ No underscore for all external C labels +;* __NOU_VAR__ No underscore for global variables only +;* +;* The default settings are for 16-bit large memory model with +;* leading underscores for symbol names. +;* +;**************************************************************************** + +%ifndef SCITECH_MAC +%define SCITECH_MAC + +; Turn off underscores for globals if disabled for all externals + +%ifdef __NOU__ +%define __NOU_VAR__ +%endif + +; Determine if we should use COFF style segment naming + +%ifdef __MSC__ +%define __COFF__ +%endif +%ifdef __GNUC__ +%define __COFF__ +%endif + +; Define the __WINDOWS__ symbol if we are compiling for any Windows +; environment + +%ifdef __WINDOWS16__ +%define __WINDOWS__ 1 +%endif +%ifdef __WINDOWS32__ +%define __WINDOWS__ 1 +%define __WINDOWS32_386__ 1 +%endif + +; Macros for accessing 'generic' registers + +%ifdef __FLAT__ +%idefine _ax eax +%idefine _bx ebx +%idefine _cx ecx +%idefine _dx edx +%idefine _si esi +%idefine _di edi +%idefine _bp ebp +%idefine _sp esp +%idefine _es +%idefine UCHAR BYTE ; Size of a character +%idefine USHORT WORD ; Size of a short +%idefine UINT DWORD ; Size of an integer +%idefine ULONG DWORD ; Size of a long +%idefine BOOL DWORD ; Size of a boolean +%idefine DPTR DWORD ; Size of a data pointer +%idefine FDPTR FWORD ; Size of a far data pointer +%idefine NDPTR DWORD ; Size of a near data pointer +%idefine CPTR DWORD ; Size of a code pointer +%idefine FCPTR FWORD ; Size of a far code pointer +%idefine NCPTR DWORD ; Size of a near code pointer +%idefine FPTR NEAR ; Distance for function pointers +%idefine DUINT dd ; Declare a integer variable +%idefine intsize 4 +%idefine flatmodel 1 +%else +%idefine _ax ax +%idefine _bx bx +%idefine _cx cx +%idefine _dx dx +%idefine _si si +%idefine _di di +%idefine _bp bp +%idefine _sp sp +%idefine _es es: +%idefine UCHAR BYTE ; Size of a character +%idefine USHORT WORD ; Size of a short +%idefine UINT WORD ; Size of an integer +%idefine ULONG DWORD ; Size of a long +%idefine BOOL WORD ; Size of a boolean +%idefine DPTR DWORD ; Size of a data pointer +%idefine FDPTR DWORD ; Size of a far data pointer +%idefine NDPTR WORD ; Size of a near data pointer +%idefine CPTR DWORD ; Size of a code pointer +%idefine FCPTR DWORD ; Size of a far code pointer +%idefine NCPTR WORD ; Size of a near code pointer +%idefine FPTR FAR ; Distance for function pointers +%idefine DUINT dw ; Declare a integer variable +%idefine intsize 2 +%endif +%idefine invert ~ +%idefine offset +%idefine use_nasm + +; Convert all jumps to near jumps, since NASM does not so this automatically + +%idefine jo jo near +%idefine jno jno near +%idefine jz jz near +%idefine jnz jnz near +%idefine je je near +%idefine jne jne near +%idefine jb jb near +%idefine jbe jbe near +%idefine ja ja near +%idefine jae jae near +%idefine jl jl near +%idefine jle jle near +%idefine jg jg near +%idefine jge jge near +%idefine jc jc near +%idefine jnc jnc near +%idefine js js near +%idefine jns jns near + +%ifdef DOUBLE +%idefine REAL QWORD +%idefine DREAL dq +%else +%idefine REAL DWORD +%idefine DREAL dd +%endif + +; Boolean truth values (same as those in debug.h) + +%idefine False 0 +%idefine True 1 +%idefine No 0 +%idefine Yes 1 +%idefine Yes 1 + +; TODO: If we wish to port VxD code to NASM, we will potentially +; need special macros in here to handle this! + +; Setup all correct segment definitions and attributes once at the +; beginning of the assembler module. This allows us to open/close +; code and data segments at will throughout the code as necessary. + +%ifdef __PIC__ +%ifdef __LINUX__ + extern _GLOBAL_OFFSET_TABLE_ +%else + extern __GLOBAL_OFFSET_TABLE_ +%endif +%endif +%ifdef __COFF__ +segment .text public class=CODE use32 flat +segment .data public class=DATA use32 flat +%else +%ifdef flatmodel +segment _TEXT public align=16 class=CODE use32 flat +segment _DATA public align=4 class=DATA use32 flat +%else +segment _TEXT public align=16 class=CODE use16 +segment _DATA public align=4 class=DATA use16 +%endif +%endif + +; Macro to be invoked at the start of all modules to set up segments for +; later use. This does nothing for 32-bit code, but for 16-bit code +; will set up a far model code segment as well for later use. + +%imacro header 1 +%ifndef flatmodel +segment %1_TEXT public align=16 class=CODE use16 +%endif +%endmacro + +; Macro to begin a data segment. Segment attributes were specified in +; the header macro that is always required. + +%imacro begdataseg 1 +%ifdef __COFF__ +segment .data +%else +segment _DATA +%endif +%endmacro + +; Macro to end a data segment + +%imacro enddataseg 1 +%endmacro + +; Macro to begin a code segment + +%imacro begcodeseg 1 +%ifdef __COFF__ +segment .text +%else +%ifdef flatmodel +segment _TEXT +%else +segment %1_TEXT +%endif +%endif +%endmacro + +; Macro to end a code segment + +%imacro endcodeseg 1 +%endmacro + +; Macro to begin a near code segment + +%imacro begcodeseg_near 0 +%ifdef __COFF__ +segment .text +%else +segment _TEXT +%endif +%endmacro + +; Macro to end a near code segment + +%imacro endcodeseg_near 0 +%endmacro + +; Macro for an extern C symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +%imacro cextern 2 +%ifdef __NOU_VAR__ +extern %1 +%else +extern _%1 +%define %1 _%1 +%endif +%endmacro + +%imacro cexternfunc 2 +%ifdef __NOU__ +extern %1 +%else +extern _%1 +%define %1 _%1 +%endif +%endmacro + +; Macro for a public C symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +%imacro cpublic 1 +%ifdef __NOU_VAR__ +global %1 +%1: +%else +global _%1 +_%1: +%define %1 _%1 +%endif +%endmacro + +; Macro for an global C symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +%imacro cglobal 1 +%ifdef __NOU_VAR__ +global %1 +%else +global _%1 +%define %1 _%1 +%endif +%endmacro + +; Macro for an global C function symbol. If the C compiler requires leading +; underscores, then the underscores are added to the symbol names, otherwise +; they are left off. The symbol name is referenced in the assembler code +; using the non-underscored symbol name. + +%imacro cglobalfunc 1 +%ifdef __PIC__ +global %1:function +%else +%ifdef __NOU__ +global %1 +%else +global _%1 +%define %1 _%1 +%endif +%endif +%endmacro + +; Macro to start a C callable function. This will be a far function for +; 16-bit code, and a near function for 32-bit code. + +%imacro cprocstatic 1 +%push cproc +%1: +%ifdef flatmodel +%stacksize flat +%define ret retn +%else +%stacksize large +%define ret retf +%endif +%assign %$localsize 0 +%endmacro + +%imacro cprocstart 1 +%push cproc + cglobalfunc %1 +%1: +%ifdef flatmodel +%stacksize flat +%define ret retn +%else +%stacksize large +%define ret retf +%endif +%assign %$localsize 0 +%endmacro + +; This macro sets up a procedure to be exported from a 16 bit DLL. Since the +; calling conventions are always _far _pascal for 16 bit DLL's, we actually +; rename this routine with an extra underscore with 'C' calling conventions +; and a small DLL stub will be provided by the high level code to call the +; assembler routine. + +%imacro cprocstartdll16 1 +%ifdef __WINDOWS16__ +cprocstart _%1 +%else +cprocstart %1 +%endif +%endmacro + +; Macro to start a C callable near function. + +%imacro cprocnear 1 +%push cproc + cglobalfunc %1 +%1: +%define ret retn +%ifdef flatmodel +%stacksize flat +%else +%stacksize small +%endif +%assign %$localsize 0 +%endmacro + +; Macro to start a C callable far function. + +%imacro cprocfar 1 +%push cproc + cglobalfunc %1 +%1: +%define ret retf +%ifdef flatmodel +%stacksize flat +%else +%stacksize large +%endif +%assign %$localsize 0 +%endmacro + +; Macro to end a C function + +%imacro cprocend 0 +%pop +%endmacro + +; Macros for entering and exiting C callable functions. Note that we must +; always save and restore the SI and DI registers for C functions, and for +; 32 bit C functions we also need to save and restore EBX and clear the +; direction flag. + +%imacro enter_c 0 + push _bp + mov _bp,_sp +%ifnidn %$localsize,0 + sub _sp,%$localsize +%endif +%ifdef flatmodel + push ebx +%endif + push _si + push _di +%endmacro + +%imacro leave_c 0 + pop _di + pop _si +%ifdef flatmodel + pop ebx + cld +%endif +%ifnidn %$localsize,0 + mov _sp,_bp +%endif + pop _bp +%endmacro + +%imacro use_ebx 0 +%ifdef flatmodel + push ebx +%endif +%endmacro + +%imacro unuse_ebx 0 +%ifdef flatmodel + pop ebx +%endif +%endmacro + +; Macros for saving and restoring the value of DS,ES,FS,GS when it is to +; be used in assembly routines. This evaluates to nothing in the flat memory +; model, but is saves and restores DS in the large memory model. + +%imacro use_ds 0 +%ifndef flatmodel + push ds +%endif +%endmacro + +%imacro unuse_ds 0 +%ifndef flatmodel + pop ds +%endif +%endmacro + +%imacro use_es 0 +%ifndef flatmodel + push es +%endif +%endmacro + +%imacro unuse_es 0 +%ifndef flatmodel + pop es +%endif +%endmacro + +; Macros for loading the address of a data pointer into a segment and +; index register pair. The %imacro explicitly loads DS or ES in the 16 bit +; memory model, or it simply loads the offset into the register in the flat +; memory model since DS and ES always point to all addressable memory. You +; must use the correct _REG (ie: _BX) %imacros for documentation purposes. + +%imacro _lds 2 +%ifdef flatmodel + mov %1,%2 +%else + lds %1,%2 +%endif +%endmacro + +%imacro _les 2 +%ifdef flatmodel + mov %1,%2 +%else + les %1,%2 +%endif +%endmacro + +; Macros for adding and subtracting a value from registers. Two value are +; provided, one for 16 bit modes and another for 32 bit modes (the extended +; register is used in 32 bit modes). + +%imacro _add 3 +%ifdef flatmodel + add e%1, %3 +%else + add %1, %2 +%endif +%endmacro + +%imacro _sub 3 +%ifdef flatmodel + sub e%1, %3 +%else + sub %1, %2 +%endif +%endmacro + +; Macro to clear the high order word for the 32 bit extended registers. +; This is used to convert an unsigned 16 bit value to an unsigned 32 bit +; value, and will evaluate to nothing in 16 bit modes. + +%imacro clrhi 1 +%ifdef flatmodel + movzx e%1,%1 +%endif +%endmacro + +%imacro sgnhi 1 +%ifdef flatmodel + movsx e%1,%1 +%endif +%endmacro + +; Macro to load an extended register with an integer value in either mode + +%imacro loadint 2 +%ifdef flatmodel + mov e%1,%2 +%else + xor e%1,e%1 + mov %1,%2 +%endif +%endmacro + +; Macros to load and store integer values with string instructions + +%imacro LODSINT 0 +%ifdef flatmodel + lodsd +%else + lodsw +%endif +%endmacro + +%imacro STOSINT 0 +%ifdef flatmodel + stosd +%else + stosw +%endif +%endmacro + +; Macros to provide resb, resw, resd compatibility with NASM + +%imacro dclb 1 +times %1 db 0 +%endmacro + +%imacro dclw 1 +times %1 dw 0 +%endmacro + +%imacro dcld 1 +times %1 dd 0 +%endmacro + +; Macro to get the addres of the GOT for Linux/FreeBSD shared +; libraries into the EBX register. + +%imacro get_GOT 1 + call %%getgot +%%getgot: pop %1 + add %1,_GLOBAL_OFFSET_TABLE_+$$-%%getgot wrt ..gotpc +%endmacro + +; Macro to get the address of a *local* variable that is global to +; a single module in a manner that will work correctly when compiled +; into a Linux shared library. Note that this will *not* work for +; variables that are defined as global to all modules. For that +; use the LEA_G macro + +%macro LEA_L 2 +%ifdef __PIC__ + get_GOT %1 + lea %1,[%1+%2 wrt ..gotoff] +%else + lea %1,[%2] +%endif +%endmacro + +; Same macro as above but for global variables public to *all* +; modules. + +%macro LEA_G 2 +%ifdef __PIC__ + get_GOT %1 + mov %1,[%1+%2 wrt ..got] +%else + lea %1,[%2] +%endif +%endmacro + +; macros to declare assembler function stubs for function structures + +%imacro BEGIN_STUBS_DEF 2 +begdataseg _STUBS +%ifdef __NOU_VAR__ +extern %1 +%define STUBS_START %1 +%else +extern _%1 +%define STUBS_START _%1 +%endif +enddataseg _STUBS +begcodeseg _STUBS +%assign off %2 +%endmacro + +%imacro DECLARE_STUB 1 +%ifdef __PIC__ + global %1:function +%1: + get_GOT eax + mov eax,[eax+STUBS_START wrt ..got] + jmp [eax+off] +%else +%ifdef __NOU__ + global %1 +%1: +%else + global _%1 +_%1: +%endif + jmp [DWORD STUBS_START+off] +%endif +%assign off off+4 +%endmacro + +%imacro SKIP_STUB 1 +%assign off off+4 +%endmacro + +%imacro DECLARE_STDCALL 2 +%ifdef STDCALL_MANGLE + global _%1@%2 +_%1@%2: +%else +%ifdef STDCALL_USCORE + global _%1 +_%1: +%else + global %1 +%1: +%endif +%endif + jmp [DWORD STUBS_START+off] +%assign off off+4 +%endmacro + +%imacro END_STUBS_DEF 0 +endcodeseg _STUBS +%endmacro + +; macros to declare assembler import stubs for binary loadable drivers + +%imacro BEGIN_IMPORTS_DEF 1 +BEGIN_STUBS_DEF %1,4 +%endmacro + +ifndef LOCAL_DECLARE_IMP +%imacro DECLARE_IMP 2 +DECLARE_STUB %1 +%endmacro + +%imacro DECLARE_PTR 2 +DECLARE_STUB %1 +%endmacro + +%imacro SKIP_IMP 2 +SKIP_STUB %1 +%endmacro + +%imacro SKIP_PTR 2 +SKIP_STUB %1 +%endmacro + +%imacro SKIP_IMP2 1 +DECLARE_STUB %1 +%endmacro + +%imacro SKIP_IMP3 1 +SKIP_STUB %1 +%endmacro +endif + +%imacro END_IMPORTS_DEF 0 +END_STUBS_DEF +%endmacro + +%endif + diff --git a/src/video/SDL_RLEaccel.c b/src/video/SDL_RLEaccel.c index e62804f1e..2106f6d6c 100644 --- a/src/video/SDL_RLEaccel.c +++ b/src/video/SDL_RLEaccel.c @@ -104,14 +104,7 @@ static char rcsid = #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) #include "mmx.h" -/* Function to check the CPU flags */ -#define MMX_CPU 0x800000 -#define CPU_Flags() Hermes_X86_CPU() -#define X86_ASSEMBLER -#define HermesConverterInterface void -#define HermesClearInterface void -#define STACKCALL -#include "HeadX86.h" +#include "SDL_cpuinfo.h" #endif #ifndef MAX @@ -657,7 +650,7 @@ do { \ if(alpha == 128) \ blitter(2, Uint8, ALPHA_BLIT16_565_50); \ else { \ - if((CPU_Flags()&MMX_CPU)!=0) \ + if(SDL_HasMMX()) \ blitter(2, Uint8, ALPHA_BLIT16_565MMX); \ else \ blitter(2, Uint8, ALPHA_BLIT16_565); \ @@ -673,7 +666,7 @@ do { \ if(alpha == 128) \ blitter(2, Uint8, ALPHA_BLIT16_555_50); \ else { \ - if((CPU_Flags()&MMX_CPU)!=0) \ + if(SDL_HasMMX()) \ blitter(2, Uint8, ALPHA_BLIT16_555MMX); \ else \ blitter(2, Uint8, ALPHA_BLIT16_555); \ @@ -698,14 +691,14 @@ do { \ || fmt->Bmask == 0xff00)) { \ if(alpha == 128) \ { \ - if((CPU_Flags()&MMX_CPU)!=0) \ + if(SDL_HasMMX()) \ blitter(4, Uint16, ALPHA_BLIT32_888_50MMX);\ else \ blitter(4, Uint16, ALPHA_BLIT32_888_50);\ } \ else \ { \ - if((CPU_Flags()&MMX_CPU)!=0) \ + if(SDL_HasMMX()) \ blitter(4, Uint16, ALPHA_BLIT32_888MMX);\ else \ blitter(4, Uint16, ALPHA_BLIT32_888); \ diff --git a/src/video/SDL_blit.c b/src/video/SDL_blit.c index 54fdcd2a9..278a523cf 100644 --- a/src/video/SDL_blit.c +++ b/src/video/SDL_blit.c @@ -38,16 +38,8 @@ static char rcsid = #include "SDL_memops.h" #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) +#include "SDL_cpuinfo.h" #include "mmx.h" -/* Function to check the CPU flags */ -#define MMX_CPU 0x800000 -#define SSE_CPU 0x2000000 -#define CPU_Flags() Hermes_X86_CPU() -#define X86_ASSEMBLER -#define HermesConverterInterface void -#define HermesClearInterface void -#define STACKCALL -#include "HeadX86.h" #endif /* The general purpose software blit routine */ @@ -166,9 +158,6 @@ static void SDL_BlitCopy(SDL_BlitInfo *info) Uint8 *src, *dst; int w, h; int srcskip, dstskip; -#if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) - Uint32 f; -#endif w = info->d_width*info->dst->BytesPerPixel; h = info->d_height; @@ -177,8 +166,7 @@ static void SDL_BlitCopy(SDL_BlitInfo *info) srcskip = w+info->s_skip; dstskip = w+info->d_skip; #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) - f=CPU_Flags(); - if((f&(MMX_CPU|SSE_CPU))==(MMX_CPU|SSE_CPU)) + if(SDL_HasSSE()) { while ( h-- ) { SDL_memcpySSE(dst, src, w); @@ -190,7 +178,7 @@ static void SDL_BlitCopy(SDL_BlitInfo *info) ::); } else - if((f&(MMX_CPU))!=0) + if(SDL_HasMMX()) { while ( h-- ) { SDL_memcpyMMX(dst, src, w); diff --git a/src/video/SDL_blit_A.c b/src/video/SDL_blit_A.c index ff4b9bdab..7f06a7907 100644 --- a/src/video/SDL_blit_A.c +++ b/src/video/SDL_blit_A.c @@ -32,16 +32,9 @@ static char rcsid = #include "SDL_blit.h" #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) -#include "mmx.h" /* Function to check the CPU flags */ -#define MMX_CPU 0x800000 -#define TDNOW_CPU 0x80000000 -#define CPU_Flags() Hermes_X86_CPU() -#define X86_ASSEMBLER -#define HermesConverterInterface void -#define HermesClearInterface void -#define STACKCALL -#include "HeadX86.h" +#include "SDL_cpuinfo.h" +#include "mmx.h" #endif /* Functions to perform alpha blended blitting */ @@ -1387,7 +1380,7 @@ SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int blit_index) if(df->Gmask == 0x7e0) { #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) - if((CPU_Flags()&MMX_CPU)!=0) + if(SDL_HasMMX()) return Blit565to565SurfaceAlphaMMX; else #endif @@ -1396,7 +1389,7 @@ SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int blit_index) else if(df->Gmask == 0x3e0) { #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) - if((CPU_Flags()&MMX_CPU)!=0) + if(SDL_HasMMX()) return Blit555to555SurfaceAlphaMMX; else #endif @@ -1413,7 +1406,7 @@ SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int blit_index) && sf->BytesPerPixel == 4) { #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) - if((CPU_Flags()&MMX_CPU)!=0) + if(SDL_HasMMX()) return BlitRGBtoRGBSurfaceAlphaMMX; else #endif @@ -1453,12 +1446,10 @@ SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int blit_index) && sf->BytesPerPixel == 4) { #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) - Uint32 f; - f=CPU_Flags(); - if((f&(TDNOW_CPU|MMX_CPU))==(TDNOW_CPU|MMX_CPU)) + if(SDL_Has3DNow()) return BlitRGBtoRGBPixelAlphaMMX3DNOW; else - if((f&MMX_CPU)!=0) + if(SDL_HasMMX()) return BlitRGBtoRGBPixelAlphaMMX; else #endif diff --git a/src/video/SDL_blit_N.c b/src/video/SDL_blit_N.c index 9cf66b972..758e87d8e 100644 --- a/src/video/SDL_blit_N.c +++ b/src/video/SDL_blit_N.c @@ -31,14 +31,7 @@ static char rcsid = #include "SDL_video.h" #include "SDL_blit.h" #include "SDL_byteorder.h" - -/* Function to check the CPU flags */ -#define MMX_CPU 0x800000 -#ifdef USE_ASMBLIT -#define CPU_Flags() Hermes_X86_CPU() -#else -#define CPU_Flags() 0L -#endif +#include "SDL_cpuinfo.h" /* Functions to blit from N-bit surfaces to other surfaces */ @@ -1429,7 +1422,7 @@ struct blit_table { Uint32 srcR, srcG, srcB; int dstbpp; Uint32 dstR, dstG, dstB; - Uint32 cpu_flags; + SDL_bool cpu_mmx; void *aux_data; SDL_loblit blitfunc; enum { NO_ALPHA, SET_ALPHA, COPY_ALPHA } alpha; @@ -1466,19 +1459,19 @@ static const struct blit_table normal_blit_3[] = { static const struct blit_table normal_blit_4[] = { #ifdef USE_ASMBLIT { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000F800,0x000007E0,0x0000001F, - MMX_CPU, ConvertMMXpII32_16RGB565, ConvertMMX, NO_ALPHA }, + 1, ConvertMMXpII32_16RGB565, ConvertMMX, NO_ALPHA }, { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000F800,0x000007E0,0x0000001F, 0, ConvertX86p32_16RGB565, ConvertX86, NO_ALPHA }, { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000007E0,0x0000F800, - MMX_CPU, ConvertMMXpII32_16BGR565, ConvertMMX, NO_ALPHA }, + 1, ConvertMMXpII32_16BGR565, ConvertMMX, NO_ALPHA }, { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000007E0,0x0000F800, 0, ConvertX86p32_16BGR565, ConvertX86, NO_ALPHA }, { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x00007C00,0x000003E0,0x0000001F, - MMX_CPU, ConvertMMXpII32_16RGB555, ConvertMMX, NO_ALPHA }, + 1, ConvertMMXpII32_16RGB555, ConvertMMX, NO_ALPHA }, { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x00007C00,0x000003E0,0x0000001F, 0, ConvertX86p32_16RGB555, ConvertX86, NO_ALPHA }, { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000003E0,0x00007C00, - MMX_CPU, ConvertMMXpII32_16BGR555, ConvertMMX, NO_ALPHA }, + 1, ConvertMMXpII32_16BGR555, ConvertMMX, NO_ALPHA }, { 0x00FF0000,0x0000FF00,0x000000FF, 2, 0x0000001F,0x000003E0,0x00007C00, 0, ConvertX86p32_16BGR555, ConvertX86, NO_ALPHA }, { 0x00FF0000,0x0000FF00,0x000000FF, 3, 0x00FF0000,0x0000FF00,0x000000FF, @@ -1581,8 +1574,7 @@ SDL_loblit SDL_CalculateBlitN(SDL_Surface *surface, int blit_index) dstfmt->Gmask == table[which].dstG && dstfmt->Bmask == table[which].dstB && (a_need & table[which].alpha) == a_need && - (CPU_Flags()&table[which].cpu_flags) == - table[which].cpu_flags ) + (table[which].cpu_mmx == SDL_HasMMX())) break; } sdata->aux_data = table[which].aux_data; diff --git a/src/video/SDL_yuv_sw.c b/src/video/SDL_yuv_sw.c index ffd67d713..7d8e786ef 100644 --- a/src/video/SDL_yuv_sw.c +++ b/src/video/SDL_yuv_sw.c @@ -92,27 +92,11 @@ static char rcsid = #include "SDL_error.h" #include "SDL_video.h" +#include "SDL_cpuinfo.h" #include "SDL_stretch_c.h" #include "SDL_yuvfuncs.h" #include "SDL_yuv_sw_c.h" -/* Function to check the CPU flags */ -#define MMX_CPU 0x800000 -#ifdef USE_ASMBLIT -#define CPU_Flags() Hermes_X86_CPU() -#else -#define CPU_Flags() 0L -#endif - -#ifdef USE_ASMBLIT -#define X86_ASSEMBLER -#define HermesConverterInterface void -#define HermesClearInterface void -#define STACKCALL - -#include "HeadX86.h" -#endif - /* The functions used to manipulate software video overlays */ static struct private_yuvhwfuncs sw_yuvfuncs = { SDL_LockYUV_SW, @@ -956,7 +940,7 @@ SDL_Overlay *SDL_CreateYUV_SW(_THIS, int width, int height, Uint32 format, SDL_S Uint32 *r_2_pix_alloc; Uint32 *g_2_pix_alloc; Uint32 *b_2_pix_alloc; - int i, cpu_mmx; + int i; int CR, CB; Uint32 Rmask, Gmask, Bmask; @@ -1082,14 +1066,13 @@ SDL_Overlay *SDL_CreateYUV_SW(_THIS, int width, int height, Uint32 format, SDL_S switch (format) { case SDL_YV12_OVERLAY: case SDL_IYUV_OVERLAY: - cpu_mmx = CPU_Flags() & MMX_CPU; if ( display->format->BytesPerPixel == 2 ) { #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) /* inline assembly functions */ - if ( cpu_mmx && (Rmask == 0xF800) && - (Gmask == 0x07E0) && - (Bmask == 0x001F) && - (width & 15) == 0) { + if ( SDL_HasMMX() && (Rmask == 0xF800) && + (Gmask == 0x07E0) && + (Bmask == 0x001F) && + (width & 15) == 0) { /*printf("Using MMX 16-bit 565 dither\n");*/ swdata->Display1X = Color565DitherYV12MMX1X; } else { @@ -1108,10 +1091,10 @@ SDL_Overlay *SDL_CreateYUV_SW(_THIS, int width, int height, Uint32 format, SDL_S if ( display->format->BytesPerPixel == 4 ) { #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT) /* inline assembly functions */ - if ( cpu_mmx && (Rmask == 0x00FF0000) && - (Gmask == 0x0000FF00) && - (Bmask == 0x000000FF) && - (width & 15) == 0) { + if ( SDL_HasMMX() && (Rmask == 0x00FF0000) && + (Gmask == 0x0000FF00) && + (Bmask == 0x000000FF) && + (width & 15) == 0) { /*printf("Using MMX 32-bit dither\n");*/ swdata->Display1X = ColorRGBDitherYV12MMX1X; } else {