changeset 739:22dbf364c017

Added SDL_HasMMX(), SDL_Has3DNow(), SDL_HasSSE() in SDL_cpuinfo.h
author Sam Lantinga <slouken@libsdl.org>
date Tue, 18 Nov 2003 01:27:06 +0000
parents 82b85b731fe3
children e70f80e98f60
files WhatsNew configure.in include/Makefile.am include/SDL_cpuinfo.h src/audio/SDL_mixer.c src/cpuinfo/COPYING.LIB src/cpuinfo/Makefile.am src/cpuinfo/README src/cpuinfo/SDL_cpuinfo.c src/cpuinfo/_cpuinfo.asm src/cpuinfo/_pcihelp.asm src/cpuinfo/cpuinfo.h src/cpuinfo/gcpuinfo.c src/cpuinfo/scitech.mac src/video/SDL_RLEaccel.c src/video/SDL_blit.c src/video/SDL_blit_A.c src/video/SDL_blit_N.c src/video/SDL_yuv_sw.c
diffstat 19 files changed, 2977 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/WhatsNew	Fri Nov 14 20:21:22 2003 +0000
+++ b/WhatsNew	Tue Nov 18 01:27:06 2003 +0000
@@ -3,6 +3,9 @@
 
 Version 1.0:
 
+1.2.7:
+	Added SDL_HasMMX(), SDL_Has3DNow(), SDL_HasSSE()
+
 1.2.6:
 	Added SDL_LoadObject(), SDL_LoadFunction(), and SDL_UnloadObject()
 
--- a/configure.in	Fri Nov 14 20:21:22 2003 +0000
+++ b/configure.in	Tue Nov 18 01:27:06 2003 +0000
@@ -503,6 +503,7 @@
             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 @@
 # 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/timer/Makefile
 src/endian/Makefile
 src/file/Makefile
+src/cpuinfo/Makefile
 src/hermes/Makefile
 sdl-config
 SDL.spec
--- a/include/Makefile.am	Fri Nov 14 20:21:22 2003 +0000
+++ b/include/Makefile.am	Tue Nov 18 01:27:06 2003 +0000
@@ -11,6 +11,7 @@
 	SDL_byteorder.h		\
 	SDL_cdrom.h		\
 	SDL_copying.h		\
+	SDL_cpuinfo.h		\
 	SDL_endian.h		\
 	SDL_error.h		\
 	SDL_events.h		\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/SDL_cpuinfo.h	Tue Nov 18 01:27:06 2003 +0000
@@ -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 */
--- a/src/audio/SDL_mixer.c	Fri Nov 14 20:21:22 2003 +0000
+++ b/src/audio/SDL_mixer.c	Tue Nov 18 01:27:06 2003 +0000
@@ -34,28 +34,13 @@
 #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 @@
 
 		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 @@
 
 		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);
 			}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpuinfo/COPYING.LIB	Tue Nov 18 01:27:06 2003 +0000
@@ -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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpuinfo/Makefile.am	Tue Nov 18 01:27:06 2003 +0000
@@ -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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpuinfo/README	Tue Nov 18 01:27:06 2003 +0000
@@ -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/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpuinfo/SDL_cpuinfo.c	Tue Nov 18 01:27:06 2003 +0000
@@ -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 <stdio.h>
+
+int main()
+{
+	printf("MMX: %d\n", SDL_HasMMX());
+	printf("3DNow: %d\n", SDL_Has3DNow());
+	printf("SSE: %d\n", SDL_HasSSE());
+}
+
+#endif /* TEST_MAIN */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpuinfo/_cpuinfo.asm	Tue Nov 18 01:27:06 2003 +0000
@@ -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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpuinfo/_pcihelp.asm	Tue Nov 18 01:27:06 2003 +0000
@@ -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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpuinfo/cpuinfo.h	Tue Nov 18 01:27:06 2003 +0000
@@ -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 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpuinfo/gcpuinfo.c	Tue Nov 18 01:27:06 2003 +0000
@@ -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
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cpuinfo/scitech.mac	Tue Nov 18 01:27:06 2003 +0000
@@ -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
+
--- a/src/video/SDL_RLEaccel.c	Fri Nov 14 20:21:22 2003 +0000
+++ b/src/video/SDL_RLEaccel.c	Tue Nov 18 01:27:06 2003 +0000
@@ -104,14 +104,7 @@
 
 #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 @@
 			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 @@
 			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 @@
 		       || 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);	\
--- a/src/video/SDL_blit.c	Fri Nov 14 20:21:22 2003 +0000
+++ b/src/video/SDL_blit.c	Tue Nov 18 01:27:06 2003 +0000
@@ -38,16 +38,8 @@
 #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 @@
 	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 @@
 	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 @@
 		::);
 	}
 	else
-	if((f&(MMX_CPU))!=0)
+	if(SDL_HasMMX())
 	{
 		while ( h-- ) {
 			SDL_memcpyMMX(dst, src, w);
--- a/src/video/SDL_blit_A.c	Fri Nov 14 20:21:22 2003 +0000
+++ b/src/video/SDL_blit_A.c	Tue Nov 18 01:27:06 2003 +0000
@@ -32,16 +32,9 @@
 #include "SDL_blit.h"
 
 #if defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT)
+/* Function to check the CPU flags */
+#include "SDL_cpuinfo.h"
 #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"
 #endif
 
 /* Functions to perform alpha blended blitting */
@@ -1387,7 +1380,7 @@
 		    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 @@
 		    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 @@
 		   && 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 @@
 	       && 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
--- a/src/video/SDL_blit_N.c	Fri Nov 14 20:21:22 2003 +0000
+++ b/src/video/SDL_blit_N.c	Tue Nov 18 01:27:06 2003 +0000
@@ -31,14 +31,7 @@
 #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 @@
 	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_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 @@
 			     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;
--- a/src/video/SDL_yuv_sw.c	Fri Nov 14 20:21:22 2003 +0000
+++ b/src/video/SDL_yuv_sw.c	Tue Nov 18 01:27:06 2003 +0000
@@ -92,27 +92,11 @@
 
 #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 @@
 	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 @@
 	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 @@
 		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 {