How do I identify x86 vs. x86_64 at compile time in gcc? - c

I want to compile part of my code only on x86 and x86_64 linux, but not s390 linux or others. How to use the macro define in C to achieve it? I know linux is to determine linux OS, and 386, 486 and 586 to determine CPU architecture. Is there an easy macro define to determine x86 linux and x86_64 linux? Thanks

You can detect whether or not you are in a 64 bit mode easily:
#if defined(__x86_64__)
/* 64 bit detected */
#endif
#if defined(__i386__)
/* 32 bit x86 detected */
#endif

If your compiler does not provide pre-defined macros and constants, you may define it yourself: gcc -D WHATEVER_YOU_WANT.
Additional reward: if you compile your code for, say, amd64, but you don't define amd64, you can compare the results (the version which use amd64-specific parts vs the generic version) and see, whether your amd64 optimalization worths the effort.

Another option instead of pre-processor macros is sizeof(void*) == 4 to detect 32-bit and/or sizeof(void*) == 8 for 64-bit. This is more portable, as it does not rely on any defined symbols or macros.
As long as your compiler has any level of optimization enabled, it should be able to see that this kind of statement is either always true or always false for the current build target, so the resulting binary should be no less efficient than if you'd used pre-processor macros.

Related

What are the requirements to use __float128?

I'm not really sure how I can find out of a system does or doesn't support the __float128 type. What system requirements have to be met for this to be available, and is there a way to check if those requirements are met in C code? (For reference, my system supports __int128 but not __float128.)
Suppose you are asking about GCC, clause 6.12 of the documentation for GCC 10.2 says:
… __float128 is available on i386, x86_64, IA-64, and hppa HP-UX, as well as on PowerPC GNU/Linux targets that enable the vector scalar (VSX) instruction set. __float128 supports the 128-bit floating type. On i386, x86_64, PowerPC, and IA-64 other than HP-UX, __float128 is an alias for _Float128. On hppa and IA-64 HP-UX, __float128 is an alias for long double…
and:
… In order to use _Float128, __float128, and __ibm128 on PowerPC Linux systems, you must use the -mfloat128 option. It is expected in future versions of GCC that _Float128 and __float128 will be enabled automatically…
I do not see an in-source test for the type, such as a preprocessor macro that would indicate it.

How to check that microprocessor is Altera Nios?

I writes some C-program code for Altera/Nios II microprocessor (uP). This code will be different with Altera Arm 9 microprocessor. So I need to write 2 different code pieces for different uP-s. How can I check in execution time which uP is present. Or more simple, current uP is Nios or not.
As the two processors are from different architectures, you will not be able to check which processor is running at run-time. You could do it at compile time, as you will have a specific define flag set by your toolchain (see https://sourceforge.net/p/predef/wiki/Architectures/). For Arm it should be __arm__ or similar, depending on the toolchain you are using for the HPS.
#ifdef __arm__
<specific code for HPS>
#else
<specific code for NIOS>
#endif /* __arm__ */
You can also look at the toolchain's defines using the c pre-processor command (cpp):
<toolchain>-cpp -dM /dev/null
Note: for Arm processor, the MIDR register could be used to know which type you are running and this one could be accessed at runtime. But when building for NIOS II, you would have a compilation error. So you need to use the preprocessor to call specific Arm register name and to remove the code when building for NiosII.
Presumably it will be compiled with a different compiler? These compilers will (very likely) have a #define of some sort which you can use to build different code for each one.
You can make the compiler dump all its default preprocessor defines using:
echo | ./nios2-elf-gcc.exe -dM -E -
This will in particular emit:
#define nios2 1

How to tell if program is running on x86/x64 or ARM Linux platforms

In a c program I want to do different things. This program will run on x86/x64 based GNU/Linux system as well as ARM based one e.g. on a PC or RaspberryPI.
Is there predefined macros in GCC to tell the platform?
something like
#ifdef _X64_
/do x64 stuff
#elif _ARM_
//do arm stuff
#endif
Or maybe that is the wrong approach? I will be using Makefileto compile and I could get away with my own defines.
What would be the best/safest approach?
This has already been answered on these posts:
GCC predefined macros for architecture X, Detecting CPU architecture compile-time
You can have them here:
http://sourceforge.net/p/predef/wiki/Architectures/
Your approach should only be used for small portions of code or functions but it should work.
Edit:
Basically, because links can become invalid:
__arm__ should work on ARM.
__x86_64__ should work on x64 architecture.
And yes, you can do:
#ifdef __x86_64__
// do x64 stuff
#elif __arm__
// do arm stuff
#endif

How to check if the machine running on is 32 or 64 bit in C?

is there any preprocessor directive or other methods to check if the machine being run is 32 bit or 64 bit in C? I've tried googling this, but the problem with C is it brings up results for C#, C++, etc.. Also, I would prefer if this worked on Windows, Linux, and Mac.
The obvious way to do this at run time.
#include <limits.h>
#include <stdio.h>
int main()
{
printf("%d bits\n", (int)(CHAR_BIT * sizeof(void *)));
return 0;
}
Technically, this is not 100% guaranteed to work. Practically, this will work with most modern compilers - it is unusual for a void pointer to be represented using a number of bits that differs from that of the underlying system architecture.
To do a compile time check, there is no standard way. It is necessary to resort to macros that are specific to your compiler/preprocessor. You will therefore need to read relevant documentation.
For Linux and OS X:
#include <sys/utsname.h>
struct utsname a;
uname (&a);
a->machine will be the string x86_64 on 64bit Intel machines, probably i586 or i686 on 32bit. You could do conditional compiling for these and whatever Windows uses.
This isn't necessarily indicative of the machine that is running (read: not true when cross-compiling), but there are some preprocessor directives.
You can determine 32/64 bit from the architecture, the most common ones are:
// 64-bit
__x86_64__
// 32-bit
__i386__ ... __i686__
You can read a whole bunch of these here, for nearly any modernish processor:
http://sourceforge.net/p/predef/wiki/Architectures/
If this worked on Windows, I have some method.
check whether the reg HKEY_CURRENT_USER\Software\Wow6432Node exists;
check whether the file C:\Windows\SysWOW64 exists;
use Windows API(IsWow64Process), please read MSDN.
You can use the following preprocessor directives to check if the machine is x86_64 in C. If it is 64-bit it sets the #define BUILD_64 flag. You then just check #ifdef BUILD_64 as the test throughout your code:
#if defined(__LP64__) || defined(_LP64)
# define BUILD_64 1
#endif

How to identify a 64 Bit build on Linux using the preprocessor?

I am about to port a Windows 32 Bit application to 64 Bit, but might decide to port the whole thing to Linux later.
The code contains sections which are dependent on the amount of memory available to the application (which depends on whether I'm creating a 32 or 64 Bit build), while the ability to compile a 32 Bit version of the code should be preserved for backward compatibility.
On Windows, I am able to simply wrap the respective code sections into preprocessor statements to ensure the right version of the code is compiled.
Unfortunately I have very few experience on programming on the Linux platform, so the question occurred:
How am I able to identify a 64 Bit build on the Linux platform?
Is there any (preferably non-compiler-specific) preprocessor define I might check for this?
Thanks in advance!
\Bjoern
Assuming you are using a recent GNU GCC compiler for IA32 (32-bit) and amd64 (the non-Itanium 64-bit target for AMD64 / x86-64 / EM64T / Intel 64), since very few people need a different compiler for Linux (Intel and PGI).
There is the compiler line switch (which you can add to CFLAGS in a Makefile) -m64 / -m32 to control the build target.
For conditional C code:
#if defined(__LP64__) || defined(_LP64)
#define BUILD_64 1
#endif
or
#include <limits.h>
#if ( __WORDSIZE == 64 )
#define BUILD_64 1
#endif
While the first one is GCC specific, the second one is more portable, but may not be correct in some bizarre environment I cannot think of.
At present both should both work for IA-32 / x86 (x86-32) and x86-64 / amd64 environments correctly. I think they may work for IA-64 (Itanium) as well.
Also see Andreas Jaeger's paper from GCC Developer's Summit entitled, Porting to 64-bit GNU/Linux Systems which described 64-bit Linux environments in additional detail.
According to the GCC Manual:
__LP64__
_LP64
These macros are defined, with value 1, if (and only if) the
compilation is for a target where long
int and pointer both use 64-bits and
int uses 32-bit.
That's what you need, right?
Also, you can try
#define __64BIT (__SIZEOF_POINTER__ == 8)

Resources