IRIX 6.5 » Books » Developer »
MIPSpro N32/64 Compiling and Performance Tuning Guide
(document number: 007-2360-010 / published: 2003-08-15)
table of contents | additional info | download find in page
Chapter 6. Porting Code to N32 and 64-Bit SGI Systems
This chapter explains the levels of compatibility between the new 32-bit
compilation mode (n32), the old 32-bit mode, and 64-bit programs. It also
describes the porting procedure to follow and the changes you must make to
port your application from old 32-bit mode to n32-bit mode. For more details,
see the MIPSpro 64-Bit Porting and Transition Guide
Specifically, this chapter discusses the following topics:
This chapter uses the following terminology:
| o32 | The old 32-bit ABI generated by the ucode compiler; that is,
32-bit compilers prior to IRIX 6.1 operating system. For information about
this compiler, see the MIPS O32 Compiling and Performance Tuning Guide
| | n32 | The new 32-bit ABI generated by the MIPSPro 64-bit compiler
(for a list of n32 features, see Chapter 1, “About the MIPSpro Compiler System”). For
information about the n32 ABI, see the MIPSpro N32 ABI Handbook.
|
In order to execute different ABIs, support must exist at three levels:
The operating system must support the ABI.
The libraries must support the ABI.
The application must be recompiled with a compiler that supports
the ABI.
Figure 6-1, shows how applications
rely on library support to use the operating system resources that they need.
 | Note:
Each o32, n32, and n64 application must be
linked against unique libraries that conform to its respective ABI. As a result,
you cannot mix and match object files or libraries from
any of the different ABIs.
|
Figure 6-2, illustrates the library locations
for different ABIs.
An operating system that supports all three ABIs is also needed for
running the application. Consequently, all applications that want to use the
features of n32 must be ported. The next section covers the steps in porting
an application to the N32 ABI.
This section describes the guidelines/steps necessary to port IRIX 5.
x 32-bit applications to n32. Typically, any porting project
can be divided into the following tasks:
Each of these tasks is described in the following sections. You can
also find additional information about n32 in the MIPSpro N32 ABI Handbook.
The porting environment consists of a compiler and associated tools,
include files, libraries, and makefiles, all of which are necessary
to compile and build your application. To generate n32 code, you must:
Check all libraries needed by your application to make sure
they are recompiled using n32. The default root location for n32 libraries
is /usr/lib32. If the n32
library needed by your application does not exist, recompile the library for
n32.
Modify existing Makefiles (or set environment variables) to
reflect the locations of these n32 libraries.
Since no differences exist in the sizes of fundamental types between
the old 32-bit mode and n32, porting to n32 requires no source code changes
for applications written in high-level languages such as C, C++, and Fortran.
The only exception to this is that C functions that accept variable numbers
of floating point arguments must be prototyped.
Assembly language code, however, must be modified to reflect the new
subprogram interface. Guidelines for following this interface are described
in Chapter 3 of the MIPSpro N32 ABI Handbook in the section titled “Assembly Language
Programming Guidelines.”
Recompiling for n32 involves either setting the -n32 argument in the compiler invocation or
running the compiler with the environment variable SGI_ABI
set to -n32. That's all you must do after you set up a
native n32 compilation environment (that is, all necessary libraries and
include files reside on the host system).
Applications that are ported to n32 may get different results than their
o32 counterparts. Reasons for this include:
Differences in algorithms used by n32 libraries and o32 libraries.
Operand reassociation or reduction performed by the optimizer
for n32.
Hardware differences of the R8000 and R1000 (madd
instructions round slightly differently than a multiply instruction
followed by an add instruction).
Porting Code to 64-Bit SGI Systems
This section covers porting code to 64-bit SGI systems, including:
You can find additional information about porting to 64-bit SGI systems
in the MIPSpro 64-Bit Porting and Transition Guide.
Data types and sizes are listed in Table 6-1.
Table 6-1. Data Types and Sizes
Data Type
| (old) 32 Bit
| n32 Bit
| 64 Bit
|
|---|
char
| 8
| 8
| 8
| short
| 16
| 16
| 16
| int
| 32
| 32
| 32
| long
| 32
| 32
| 64
| long long
| 64 (emulated with 32-bit integer operations)
| 64 (native 64-bit integer operations)
| 64
| pointer
| 32
| 32
| 64
| float
| 32
| 32
| 32
| double
| 64
| 64
| 64
| long double
| 64
| 128
| 128
| void
| 32
| 32
| 64
|
Note that in 64-bit mode, types long and
int have different sizes and ranges; a long always
has the same size as a pointer. A pointer
(or address) has 64-bit representation in 64-bit mode and 32-bit representation
in 32-bit mode. An int has a smaller range than a
pointer in 64-bit mode. On 32-bit compiles, the long double
generates a warning message indicating that the long
qualifier is not supported.
Characteristics of integral types and floating point types are defined
in the standard files limits.h and float.h.
The cc, CC, and as
compiler drivers produce predefined macros listed in Table 6-2.
These macros are used in sys/asm.h, sys/regdef.h
, and sys/fpregdef.h.
Table 6-2. Predefined Macros
32-Bit Executables
| 64-Bit Executables
|
|---|
-D_MIPS_FPSET=16
| -D_MIPS_FPSET=32
| -D_MIPS_ISA=_MIPS_ISA_MIPS1
| -D_MIPS_ISA=_MIPS_ISA_MIPS3
| -D_MIPS_SIM=_MIPS_SIM_ABI32
| -D_MIPS_SIM=_MIPS_SIM_ABI64
| -D_MIPS_SZINT=32
| -D_MIPS_SZINT=32
| -D_MIPS_SZLONG=32
| -D_MIPS_SZLONG=64
| -D_MIPS_SZPTR=32
| -D_MIPS_SZPTR=64
|
_MIPS_FPSET describes the number of floating point
registers. The 64-bit compilation mode makes use of the extended floating
point registers.
MIPS_ISA determines the MIPS Instruction Set Architecture.
MIPS_ISA_MIPS1 and MIPS_ISA_MIPS3 are the defaults
for 32 bits and 64 bits, respectively. For example:
/* Define a parameter for the integer register size: */
#if (_MIPS_ISA == _MIPS_ISA_MIPS1 || _MIPS_ISA == _MIPS_ISA_MIPS2)
#define SZREG 4
#else
#define SZREG 8
#endif |
MIPS_SIM determines the MIPS Subprogram Interface
Model, which describes the subroutine linkage convention and register naming/usage
convention.
_MIPS_SZINT, _MIPS_SZLONG, and
_MIPS_SZPTR define the size of types int,
long, and pointer, respectively.
The 64-bit MIPSpro compiler drivers generate 64-bit pointer
and long and 32-bit int.
Therefore, assembler code that uses either pointer or
long types must be converted to use double-word
instructions for MIPS III code (-64), and must continue
to use word instructions for MIPS I and MIPS II code (
-32).
Also, new subroutine linkage conventions and register naming conventions
exist. The compiler predefined macro _MIPS_SIM enables
macros in sys/asm.h and sys/regdef.h.
Eight argument registers exist: $4 through $11. Four additional
argument registers replace the temp registers in
sys/regdef.h. These temp registers are not lost,
however, as the argument registers can serve also as scratch registers, with
certain constraints.
In the _MIPS_SIM_ABI64 model, registers
t4 through t7 are not available, so any code
using these registers does not compile. Similarly, registers a4
through a7 are not available under the _MIPS_SIM_ABI32
model.
If you are converting assembler code, the new registers ta0
, ta1, ta2, and
ta3 are available under both _MIPS_SIM models.
These alias with registers t4 through t7
in 32-bit mode, and with registers a4 through
a7 in 64-bit mode.
Note that the caller no longer has to reserve space for a called function
in which to store its arguments. The called routine allocates space for storing
its arguments on its own stack, if desired. The NARGSAVE
macro in sys/asm.h
facilitates this.
This section describes typedefs that you can use
to write portable code for a range of target environments, including 32- and
64-bit workstations as well as 16- and 32-bit PCs. These typedef
s are enabled by compiler-predefined macros (listed in Table 6-2), and are in the file inttypes.h. (This
discussion applies to C, although the same macros are predefined by the C++
compiler.)
Portability problems exist because an int
(32 bits) is no longer the same size as a pointer
(64 bits) and a long (64 bits) in 64-bit programs.
Typedefs free you from having to know the underlying compilation
model or worry about type sizes. In the future, if that model changes, the
code should still work.
Typically, you want source code that you can compile either in 32- or
64-bit mode. (In this discussion, 32-bit mode implies -mips1/
2; 64-bit mode implies -mips3/4.)
The following typedefs are defined in
inttypes.h:
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed long long int int64_t;
typedef unsigned long long int uint64_t;
typedef signed long long int intmax_t;
typedef unsigned long long int uintmax_t;
typedef signed long int intptr_t;
typedef unsigned long int uintptr_t; |
The intmax_t and uintmax_t types
are guaranteed to be the largest integer type supported by this implementation.
Use them in code that must be able to deal with any integer value. intptr_t and
uintptr_t are guaranteed to be exactly the size of a pointer
.
Maximum Memory Allocation
The total memory allocation for a program, and individual arrays, can
exceed 2 gigabytes (2 Gbytes, or 2,048 Mbytes).
Previous implementations of Fortran, C, and C++ limited the total program
size, as well as the size of any single array, to 2 GBytes. The current release
allows the total memory in use by the program to exceed 2 gigabytes.
Arrays Larger Than 2 Gigabytes
The IRIX 6.2 (MIPSPro 7.1) compilers (and above) support arrays that
are larger than 2 gigabytes for programs compiled under the -64
ABI. The arrays can be local, global, and dynamically created as the following
example demonstrates. (Initializers are not provided for these arrays.) Large
array support is limited to Fortran, C, and C++.
Example of Arrays Larger Than 2 Gigabytes
The following code shows an example of arrays larger than 2 gigabytes.
#include <stdlib.h>
int i[0x100000008];
void foo()
{
int k[0x100000008];
k[0x100000007] = 9;
printf(“%d \n”, k[0x100000007]);
}
main()
{
char *j;
j = malloc(0x100000008);
i[0x100000007] = 7;
j[0x100000007] = 8;
printf(“%d \n”, i[0x100000007]);
printf(“%d \n”, j[0x100000007]);
foo();
} |
You must run this program on a 64-bit operating system with IRIX version
6.2 (or higher). You can verify the system you have by typing
uname -a. You must have enough swap space to support the working
set size and you must have your shell limit datasize,
stacksize, and vmemoryuse variables
set to values large enough to support the sizes of the arrays (see sh(1) man page).
The following example compiles and runs the preceding code after setting
the stack size to a correct value:
% uname -a
IRIX64 cydrome 6.2 03131016 IP19
$cc -64 -mips3 a2.c
$limit
cputime unlimited
filesize unlimited
datasize unlimited
stacksize 65536 kbytes
coredumpsize unlimited
memoryuse 754544 kbytes
descriptors 200
vmemoryuse unlimited
$limit stacksize unlimited
$limit
cputime unlimited
filesize unlimited
datasize unlimited
stacksize unlimited
coredumpsize unlimited
memoryuse 754544 kbytes
descriptors 200
vmemoryuse unlimited
$a.out
7
8
9 |
Using Large Files with XFS
An application may create or encounter files greater than 2 gigabytes
with the XFS file system. If a program is doing sequential I/O and does not
maintain internal byte counters, files greater than 2 gigabytes will not encounter
problems.
However, if an application uses internal byte counters, then modifications
are required. Table 6-3, lists potential problems
and modifications required to enable files greater than 2 gigbytes to run
on XFS.
Table 6-3. Modifications for Applications on XFS
Application
| Modification
|
|---|
Uses an internal byte counter while
reading
| Change to type long long
| Uses certain system calls such as
lseek() and stat() that use 32-bit off_t
| Use lseek64(),
stat64(), and so forth
| Relies on internal features of EFS
(such as reads the raw disk)
| Rewrite the application (so it does
not read the raw disk)
|
For more information about XFS, see Getting Started with XFS Filesystems.
MIPSpro N32/64 Compiling and Performance Tuning Guide
(document number: 007-2360-010 / published: 2003-08-15)
table of contents | additional info | download
Front Matter
New Features in This Manual
About This Guide
Chapter 1. About the MIPSpro Compiler System
Chapter 2. Using the MIPSpro Compiler System
Chapter 3. Using Dynamic Shared Objects
Chapter 4. Optimizing Program Performance
Chapter 5. Coding for 64-Bit Programs
Chapter 6. Porting Code to N32 and 64-Bit SGI Systems
Index
home/search |
what's new |
help
|