Commit fb25886c authored by Sam Lantinga's avatar Sam Lantinga

Greatly simplified the SDL CPU info code

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40746
parent c1da62cb
...@@ -37,6 +37,10 @@ static char rcsid = ...@@ -37,6 +37,10 @@ static char rcsid =
extern "C" { extern "C" {
#endif #endif
/* This function returns true if the CPU has the RDTSC instruction
*/
extern DECLSPEC SDL_bool SDLCALL SDL_HasRDTSC();
/* This function returns true if the CPU has MMX features /* This function returns true if the CPU has MMX features
*/ */
extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX(); extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX();
......
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
###########################################################################
#
# 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__ @NASMFLAGS@ $< -o $*.o
###########################################################################
# The cpuinfo library target # The cpuinfo library target
noinst_LTLIBRARIES = libcpuinfo.la noinst_LTLIBRARIES = libcpuinfo.la
if HAVE_NASM
ARCH_SRCS = \
_cpuinfo.asm \
_pcihelp.asm
else
ARCH_SRCS =
endif
COMMON_SRCS = \ COMMON_SRCS = \
cpuinfo.h \
gcpuinfo.c \
SDL_cpuinfo.c SDL_cpuinfo.c
libcpuinfo_la_SOURCES = $(ARCH_SRCS) $(COMMON_SRCS) libcpuinfo_la_SOURCES = $(COMMON_SRCS)
EXTRA_DIST = \
COPYING.LIB \
README
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/
...@@ -28,16 +28,160 @@ static char rcsid = ...@@ -28,16 +28,160 @@ static char rcsid =
/* CPU feature detection for SDL */ /* CPU feature detection for SDL */
#include "SDL.h" #include "SDL.h"
//#include "SDL_cpuinfo.h" #include "SDL_cpuinfo.h"
#define CPU_HAS_MMX 0x00000001 #define CPU_HAS_RDTSC 0x00000001
#define CPU_HAS_3DNOW 0x00000002 #define CPU_HAS_MMX 0x00000002
#define CPU_HAS_SSE 0x00000004 #define CPU_HAS_3DNOW 0x00000004
#define CPU_HAS_SSE 0x00000008
/* These functions come from SciTech's PM library */ static __inline__ int CPU_haveCPUID()
extern int CPU_haveMMX(); {
extern int CPU_have3DNow(); int has_CPUID = 0;
extern int CPU_haveSSE(); #if defined(__GNUC__) && defined(i386)
__asm__ (
"push %%ecx\n"
" pushfl # Get original EFLAGS \n"
" popl %%eax \n"
" movl %%eax,%%ecx \n"
" xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n"
" pushl %%eax # Save new EFLAGS value on stack \n"
" popfl # Replace current EFLAGS value \n"
" pushfl # Get new EFLAGS \n"
" popl %%eax # Store new EFLAGS in EAX \n"
" xorl %%ecx,%%eax # Can not toggle ID bit, \n"
" jz 1f # Processor=80486 \n"
" movl $1,%0 # We have CPUID support \n"
"1: \n"
"pop %%ecx\n"
: "=r" (has_CPUID)
:
: "%eax", "%ecx"
);
#elif defined(_MSC_VER)
__asm__ {
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,
jz done ; Processor=80486
mov has_CPUID,1 ; We have CPUID support
done:
}
#endif
return has_CPUID;
}
static __inline__ int CPU_getCPUIDFeatures()
{
int features = 0;
#if defined(__GNUC__) && defined(i386)
__asm__ (
"push %%ebx\n"
"push %%ecx\n"
"push %%edx\n"
" xorl %%eax,%%eax # Set up for CPUID instruction \n"
" cpuid # Get and save vendor ID \n"
" cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n"
" jl 1f # We dont have the CPUID instruction\n"
" xorl %%eax,%%eax \n"
" incl %%eax \n"
" cpuid # Get family/model/stepping/features\n"
" movl %%edx,%0 \n"
"1: \n"
"pop %%edx\n"
"pop %%ecx\n"
"pop %%ebx\n"
: "=r" (features)
:
: "%eax", "%ebx", "%ecx", "%edx"
);
#elif defined(_MSC_VER)
__asm__ {
xor eax, eax ; Set up for CPUID instruction
cpuid ; Get and save vendor ID
cmp eax, 1 ; Make sure 1 is valid input for CPUID
jl done ; We dont have the CPUID instruction
xor eax, eax
inc eax
cpuid ; Get family/model/stepping/features
mov features, edx
done:
}
#endif
return features;
}
static __inline__ int CPU_haveRDTSC()
{
if ( CPU_haveCPUID() ) {
return (CPU_getCPUIDFeatures() & 0x00000010);
}
return 0;
}
static __inline__ int CPU_haveMMX()
{
if ( CPU_haveCPUID() ) {
return (CPU_getCPUIDFeatures() & 0x00800000);
}
return 0;
}
static __inline__ int CPU_have3DNow()
{
int has_3DNow = 0;
#if defined(__GNUC__) && defined(i386)
__asm__ (
"push %%ebx\n"
"push %%ecx\n"
"push %%edx\n"
" movl $0x80000000,%%eax # Query for extended functions \n"
" cpuid # Get extended function limit \n"
" cmpl $0x80000001,%%eax \n"
" jbe 1f # Nope, we dont have function 800000001h\n"
" movl $0x80000001,%%eax # Setup extended function 800000001h\n"
" cpuid # and get the information \n"
" testl $0x80000000,%%edx # Bit 31 is set if 3DNow! present \n"
" jz 1f # Nope, we dont have 3DNow support\n"
" movl $1,%0 # Yep, we have 3DNow! support! \n"
"1: \n"
"pop %%edx\n"
"pop %%ecx\n"
"pop %%ebx\n"
: "=r" (has_3DNow)
:
: "%eax", "%ebx", "%ecx", "%edx"
);
#elif defined(_MSC_VER)
__asm__ {
mov eax,80000000h ; Query for extended functions
cpuid ; Get extended function limit
cmp eax,80000001h
jbe done ; Nope, we dont have function 800000001h
mov eax,80000001h ; Setup extended function 800000001h
cpuid ; and get the information
test edx,80000000h ; Bit 31 is set if 3DNow! present
jz done ; Nope, we dont have 3DNow support
mov has_3DNow,1 ; Yep, we have 3DNow! support!
done:
}
#endif
return has_3DNow;
}
static __inline__ int CPU_haveSSE()
{
if ( CPU_haveCPUID() ) {
return (CPU_getCPUIDFeatures() & 0x02000000);
}
return 0;
}
static Uint32 SDL_CPUFeatures = 0xFFFFFFFF; static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
...@@ -45,6 +189,9 @@ static Uint32 SDL_GetCPUFeatures() ...@@ -45,6 +189,9 @@ static Uint32 SDL_GetCPUFeatures()
{ {
if ( SDL_CPUFeatures == 0xFFFFFFFF ) { if ( SDL_CPUFeatures == 0xFFFFFFFF ) {
SDL_CPUFeatures = 0; SDL_CPUFeatures = 0;
if ( CPU_haveRDTSC() ) {
SDL_CPUFeatures |= CPU_HAS_RDTSC;
}
if ( CPU_haveMMX() ) { if ( CPU_haveMMX() ) {
SDL_CPUFeatures |= CPU_HAS_MMX; SDL_CPUFeatures |= CPU_HAS_MMX;
} }
...@@ -58,6 +205,14 @@ static Uint32 SDL_GetCPUFeatures() ...@@ -58,6 +205,14 @@ static Uint32 SDL_GetCPUFeatures()
return SDL_CPUFeatures; return SDL_CPUFeatures;
} }
SDL_bool SDL_HasRDTSC()
{
if ( SDL_GetCPUFeatures() & CPU_HAS_RDTSC ) {
return SDL_TRUE;
}
return SDL_FALSE;
}
SDL_bool SDL_HasMMX() SDL_bool SDL_HasMMX()
{ {
if ( SDL_GetCPUFeatures() & CPU_HAS_MMX ) { if ( SDL_GetCPUFeatures() & CPU_HAS_MMX ) {
...@@ -91,6 +246,7 @@ int main() ...@@ -91,6 +246,7 @@ int main()
printf("MMX: %d\n", SDL_HasMMX()); printf("MMX: %d\n", SDL_HasMMX());
printf("3DNow: %d\n", SDL_Has3DNow()); printf("3DNow: %d\n", SDL_Has3DNow());
printf("SSE: %d\n", SDL_HasSSE()); printf("SSE: %d\n", SDL_HasSSE());
return 0;
} }
#endif /* TEST_MAIN */ #endif /* TEST_MAIN */
;****************************************************************************
;*
;* 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
;****************************************************************************
;*
;* 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
/****************************************************************************
*
* 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 */
/****************************************************************************
*
* 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
}
;****************************************************************************
;*
;* ========================================================================
;*
;* 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment