[ First ]  [ Previous ]  [ Next ]  [ Last ]  [ Manuals ]

 

Chapter 9.

 

C and C++ Support for Power PC



This chapter describes both the CodeWarrior back-end compiler and linker for PowerPC/AltiVec.

The topics in this chapter are:

This chapter also discusses the numerous extensions to the compiler for supporting AltiVec features, like preprocessor macros, vector data types, and alignment considerations.

However, this chapter does not discuss several important topics with respect to code generation, including front-end compiler issues, compiler and linker errors, controlling the size of C++ code, and so forth. These topics are covered in other CodeWarrior documentation as outlined in Table 9.1.

The "back-end" of the compiler refers to the module that actually generates code for the target processor. The "front-end" refers to the module that parses and interprets your source code. See the C Compiler Reference for additional compiler and linker information.

Other compiler/linker documentation:

 

For this topic...
See...
How CodeWarrior implements the C/C++ language  
C Compilers Reference generally  
Using C/C++ Language and C/C++ Warnings settings panels  
C Compilers Reference, "Using C/C++ in the CodeWarrior IDE" chapter  
Controlling the size of C++ code  
C Compilers Reference, "C++ and Embedded Systems" chapter  
Using compiler pragmas  
C Compilers Reference, "Pragmas" chapter  
Using compiler symbols  
C Compilers Reference, "Symbols" chapter  
Initiating a build, controlling which files are compiled, handling error reports  
IDE User Guide, "Compiling and Linking" chapter  
Information about a particular error  
Error Reference online help  

You may find the following website to be worth a careful look:

	http://motorola.com/SPS/PowerPC/

Predefined Preprocessor Macros

When compiling your code, you can take advantage of some predefined preprocessor symbols for conditionally compiling code. You can find a list of these in the C Compilers Reference. For more information on pragmas, refer to "Pragmas."

In particular, the following symbols are defined:


__A5__

Defined as 1 if data is A5-relative, 0 if data is A4 relative. This symbol is defined for 68K compilers. It is undefined for other target platforms.


__ALTIVEC__

This symbol is set to a value indicating the feature level of the AltiVec compiler. It currently returns 100000000. This means that the AltiVec-specific instructions are supported in the compiler and are available for use. You may find pragmas to be useful in working with AltiVec.


__fourbyteintegers__

Defined as 1, if you turn on the 4-byte Ints option in the 68K Processor settings panel. 0, if you turn off that option. This symbol is defined for 68K compilers. It is undefined for other platforms.


__IEEEdoubles__

Defined as 1 if you turn on the 8-Byte Doubles option in the 68K Processor settings panel. 0, if you turn off that option. This symbol is defined for 68K compilers. It is undefined for all other target platforms.


__MACOS__

The Metrowerks compilers for MacOS define the __MACINTOSH__ symbol. You can conditionalize platform-dependent code using this symbol in a statement such as this:


#ifdef __MACINTOSH__
... your code here
#endif


__MC68020__

Defined as 1 if you turn on the 68020 Codegen option in the Processor settings panel, 0 if you turn that option off. This symbol is defined for 68K compilers. It is undefined for all other target platforms.


__MC68881__

Defined as 1 if you turn on the 68881 Codegen option in the 68K Processor settings panel, 0 if you turn that option off. This symbol is defined for 68K compilers and undefined for all other target platforms.


__MC68K__

Defined as 1 if you're compiling this code with the 68K compiler and undefined for all other target platforms.


powerc

Another trick you might find useful for conditionalizing 68K and PowerPC code works as illustrated here.


#if defined(powerc)
		/* do something for PowerPC */
#else
    SetA5(oldA5); /* set A5 world for 68K */
#endif


__VEC__

If this is defined, then the generation of AltiVec instructions is currently enabled. The value returned by this symbol indicates the version of the AltiVec Pramming Interface Manual which the compiler conforms to. This is currently 10205, or when converted to decimal reads 1.2.5. This is typically used in this form:


#if __VEC__
// do stuff here...
#endif

This is enabled via the PPC Processor panel or with the pragma:


#pragma altivec_model [on | off]

Table 9.2 shows all the currently used proprocessor symbols and their values.

Preprocessor symbol values:

 

Preprocessor
Value
powerc  
1, may not be allowed when ANSI strict is on in the future  
__powerc  
1  
__POWERPC__  
1  
__BIG_ENDIAN__  
1  
Altivec  
__VEC__  
10205  
__ALTIVEC__  
100000000  
Mac OS  
macintosh  
1, may not be allowed when ANSI strict is on in the future  
__MACOS__  
1  
Mach-O  
__APPLE__  
1  
__MACH__  
1  
__ARCHITECTURE__  
ppc  
__OPTIMIZE__  
0-4, optimization level  
__DYNAMIC__  
1, when Dynamic Addressing Model is selected  
__STATIC__  
1, when Dynamic Addressing Model is not selected  
__NATURAL_ALIGNMENT__  
1  
ppc  
1, not allowed when ANSI strict is on  
__ppc__  
1  


Number Formats

This section describes how the CodeWarrior C/C++ compilers implement integer and floating-point types for PowerPC processors. You can also read about limits.h for more information on integer types, and float.h for more information on floating-point types in the MSL C Reference. You may also find the altivec.h file interesting.

The topics in this section are:


AltiVec Vector Data Formats

There are 11 new vector data types for use in writing AltiVec-specific code, shown in Table 9.3. Notice that all the types are a constant size, either 128 bits or 16 bytes. This is due to the AltiVec programming model which is optimized for quantities of this size.

AltiVec Vector Data Types:

 

Vector Data Type
Size (bytes)
Contents
Possible Values
vector unsigned char  
16  
16 unsigned char  
0 to 255  
vector signed char  
16  
16 signed char  
-128 to 127  
vector bool char  
16  
16 unsigned char  
0 = false, 255 = true  
vector unsigned short  
16  
8 unsigned short  
0 to 65535  
vector signed short  
16  
8 signed short  
-32768 to 32767  
vector bool short  
16  
8 unsigned short  
0 = false,
65535 = true  
vector unsigned int  
16  
4 unsigned int  
0 to 232 - 1  
vector signed int  
16  
4 signed int  
-231 to 231-1  
vector bool int  
16  
4 unsigned int  
0 = false,
2^32-1 = true  
vector float  
16  
4 float  
any IEEE-754 value  
vector pixel  
16  
8 unsigned short  
1/5/5/5 pixel  

The types shown in Table 9.4 still work, but are deprecated and are not recommended for use. The preferred types to use instead are vector signed int, vector unsigned int, and vector bool int. In the table, the [int] portion of the Vector Data Type is optional except in the case of 32-bit integer elements.


NOTE

Always use int instead of long to designate 32-bit elements. long is now deprecated and should only appear in legacy code.


Deprecated AltiVec Types:

 

Vector Data Type
Size (bytes)
Contents
Possible Values
vector unsigned long [int]  
16  
4 unsigned int  
0 to 232 - 1  
vector signed long [int]  
16  
4 signed int  
-231 to 231-1  
vector bool long [int]  
16  
4 unsigned int  
0 = false, 1 = true  

There are two additional keywords besides pixel and vector, __pixel and __vector. These keywords can be used in C or C++ code.

bool is not a reserved word in C unless it is used as an AltiVec vector data type.


Integer Formats

Table 9.5 shows the size and range of the integer types for the PowerPC compiler.

PowerPC Integer Types:

 

For this type
Option setting
Size is
and its range is
bool  
n/a  
8 bits  
true or false  
char  
Use Unsigned Chars is off  
8 bits  
-128 to 127 (see language preferences panel in the C Compilers Reference)  
Use Unsigned Chars is on  
8 bits  
0 to 255  
signed char  
n/a  
8 bits  
-128 to 127  
unsigned char  
n/a  
8 bits  
0 to 255  
short  
n/a  
16 bits  
-32,768 to 32,767  
unsigned short  
n/a  
16 bits  
0 to 65,535  
int  
n/a  
32 bits  
-2,147,483,648 to 2,147,483,647  
unsigned int  
n/a  
32 bits  
0 to 4,294,967,295  
long  
n/a  
32 bits  
-2,147,483,648 to 2,147,483,647  
unsigned long  
n/a  
32 bits  
0 to 4,294,967,295  
long long  
n/a  
64 bits  
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807  
unsigned long long  
n/a  
64 bits  
0 to 18,446,744,073,709,551,615  


Floating-Point Formats

Table 9.6 shows the sizes and ranges of the floating point types for the PowerPC Mac OS compiler.

PowerPC floating point types:

 

Type  
Size  
Range  
float  
32 bits  
1.17549e-38 to 3.40282e+38  
short double  
64 bits  
2.22507e-308 to 1.79769e+308  
double  
64 bits  
2.22507e-308 to 1.79769e+308  
long double  
64 bits  
2.22507e-308 to 1.79769e+308  



Register Variables

(K&R, §A4.1, §A8.1) The PowerPC back-end compiler automatically allocates local variables and parameters to registers according to how frequently they're used and how many registers are available. If you're optimizing for speed, the compiler give preference to variables used in loops.

The PowerPC back-end compiler gives preference to variables declared to be register, but does not automatically assign them to registers. For example, the compiler is more likely to place a variable from an inner loop in a register than a variable declared register.


Optimizing Code

This section discusses optimizations that are specific to PowerPC development with CodeWarrior.


Register Coloring

The PowerPC back-end compiler can perform a register optimization called register coloring. In this optimization, the compiler lets two or more variables share a register. It assigns different variables or parameters to the same register if you do not use the variables at the same time. In this example, the compiler could place i and j in the same register:


short i;
int j;
for (i=0; i<100; i++) {  MyFunc(i); }
for (j=0; j<1000; j++) {  OurFunc(j); }

However, if a line like the one below appears anywhere in the function, the compiler would realize that you're using i and j at the same time and place them in different registers:


int k = i + j;

You control whether the PPC back-end compiler performs the register coloring optimization from the Global Optimizations settings panel. Refer to the IDE User Guide for information on this panel.

If Register Coloring is on while you debug your project, it may appear as though there's something wrong with the variables sharing a register. In the example above, i and j would always have the same value. When i changes, j changes in the same way. When j changes, i changes in the same way. To avoid this confusion while debugging, turn off Register Coloring or declare the variables you want to watch as volatile.


Pragmas

This section discusses pragmas you can use in your development. The two types of pragmas are:

These pragmas, pragma syntax, and how to determine and modify the state of the compiler using pragmas are all detailed in the C Compilers Reference.


PowerPC Pragmas

Table Table 9.7 list the pragmas supported for PowerPC development.

Pragmas for PowerPC development:

 

align  
opt_strength_reduction  
align_array_  
opt_strength_reduction_strict  
always_inline  
opt_unroll_loops  
ANSI_strict  
opt_vectorize_loops  
ARM_conform  
peephole  
auto_inline  
pool_data  
bool  
pool_strings  
check_header_  
pop  
cplusplus  
ppc_unroll_factor_limit  
cpp_extensions  
ppc_unroll_instructions_limit  
defer_codegen  
ppc_unroll_speculative  
def_inherited  
precompile_target  
direct_to_som  
profile  
disable_registers  
push  
dollar_identifiers  
readonly_strings  
dont_inline  
require_prototypes  
dont_reuse_  
RTTI  
enumsalwaysints  
schedule [different from "#pragma scheduling"]  
errorcheck  
scheduling  
exceptions  
segment [applies to Mac OS/PowerPC programming, not just Mac OS/68K]  
extended_  
side_effects  
faster_pch_gen  
simple_prepdump  
flags  
SOMCallOptimization  
float_constants  
SOMCallStyle  
force_active  
SOMCheckEnvironment  
fp_contract  
SOMClassVersion  
fullpath_prepdump  
SOMMetaClass  
function_align  
SOMReleaseOrder  
gcc_extensions  
static_inlines  
global_optimizer  
strings  
ignore_oldstyle  
suppress_init_code  
import  
supress_warnings  
inline_bottom_up  
sym  
inline_depth  
syspath_once  
internal  
syspath_once  
lib_export  
toc_data  
line_prepdump  
traceback  
longlong  
trigraphs  
longlong_enums  
unsigned_char  
longlong_prepval  
unused  
mark  
warning_errors  
members  
warn_emptydecl  
message  
warn_extracomma  
mpwc_newline  
warn_hidevirtual  
mpwc_relax  
warn_illpragma  
no_static_dtors  
warn_implicitconv  
once  
warn_notinlined  
only_std_keywords  
warn_no_side_effect  
optimization_level  
warn_padding  
optimize_for_size  
warn_possunwant  
opt_common_subs  
warn_resultnotused  
opt_dead_assignments  
warn_structclass  
opt_dead_code  
warn_unusedarg  
opt_lifetimes  
warn_unusedvar  
opt_loop_invariants  
wchar_type  
opt_propagation  
 


AltiVec Pragmas

There are a couple of pragmas you might find useful in working with AltiVec code.


#pragma altivec_model [on | off | reset]

This pragma turns on AltiVec code generation and vectorization. Use it to make a portion of your code generate AltiVec instructions.

If this is placed outside a function, then the effect continues until another one of these pragmas is encountered outside a function. If reset is specified, the setting is changed to off.

If the pragma is used inside a function, the effect of the pragma is for that function only. Even if the pragma does not occur at the beginning of the function, the entire function will be treated. One, and only one, instance of this pragma can occur inside a function. This implies that inside a function the reset form of this pragma is illegal.


#pragma scheduling altivec

This pragma is needed to turn on AltiVec instruction scheduling. Instead of specifying altivec there are also other values that are legal. Using 7400 is the same as altivec.

In addition, you might find the following pragmas helpful.


#pragma schedule once
#pragma schedule twice

On highly-optimized C code where loops have been unrolled by hand, running the scheduler once is better than running it twice. This especially applies in routines where the register usage is relatively high. Scheduling introduces register pressure before register colorizing causing excessive spilling of registers to memory. When the scheduler is run twice it is run before and after register coloring. If it is only run once after register coloring.


#pragma altivec_vrsave [on | off | allon]

This pragma is used to turn VRSAVE updating on or off. If you turn it off, you will have to set save the state yourself. Using allon sets VRSAVE assuming that all AltiVec registers are in use. You can use this in conjunction with the off version of this pragma so that only the parent routine updates the VRSAVE register.

Other pragmas that may be useful for optimizations are:


#pragma ppc_unroll_instructions_limit
#pragma_unroll_factor_limit
#pragma ppc_unroll_speculative

You might want to make use of this pragma in order to obtain more favorable execution times due to proper memory alignment:


#pragma function_align [4|8|16|32|64|128|reset]


Constants

There are a couple of considerations to note when working with constants in your code.

Variables that are marked const should be placed in a read-only section whenever possible. However, in some cases C++ const variables are initialized at runtime so they can't be placed in a read-only section.

For AltiVec, constants are pooled. Saving vector constants in the TOC will not be successful, and this option is ignored.


Alignment Considerations for AltiVec

For AltiVec processors, alignment is critical to proper performance. A data location for a vector quantity must be aligned on a 16-byte boundary. The compiler forces this alignment when generating code, however, you should be aware of it if you are writing assembly code.

If you try to access a quantity on a non-aligned boundary, such as during a pointer dereferencing operation, the low-order bits of the address are ignored.

The topics discussed in this section are:


Non-Vector Data

When stuffing vector registers with data, the data does not have to be aligned. When accessing it you need to use the operators provided for this purpose, like vec_perm(), vec_lvsl(), and vec_lvsr().


Embedded Vector Data

If your data structures or classes contain data of type vector then the class or structure will be aligned on 16-byte boundaries. Any padding or packing required to bring about this alignment internally to the structure or class is done by the compiler. Any alignment pragmas are ignored for the purposes of arranging this embedded vector data.


Dynamic Allocation

All dynamic allocations for containing vector data must be 16-byte aligned. This is required whether the space is created on the stack at runtime by the compiler, or by the user. Also, heap allocations and C++ class objects instantiations are also aligned.


Compiler Local Variables

The compiler will generate any needed function entry "prolog" code to ensure 16-byte alignment. This code makes sure that the stack variables in the function are 16-byte aligned. The code is not always necessary, but if it is, the compiler will put it there. This is typically only required when parameters or local variables for the function are vector type.


Stack Data

The code generated by the compiler for stack variables will be 16-byte aligned when vector data is present.


Heap Data

Using the vec_malloc() operator is required in certain cases to obtain 16-byte alignment. This is similar to, and replaces, the ubiquitous malloc() call for vector data. In addition, vec_realloc() replaces realloc() and vec_calloc() replaces calloc(). These are defined in stdlib.h.

In order to preserve 16-byte alignment you should always use the vec_ equivalents of these popular functions when the space allocated will contain vector data.

You will need to use vec_free() to unallocate any space that you requested with these vector allocation operators.


Object Data

When default operator new is invoked for a class that has vector data someplace in the class definition or inheritance tree, vec_new() is invoked instead of the normal runtime new operator. The analogous situation is true for delete, in which case vec_delete() is called. If you define your own new or delete operator, you are responsible for properly-allocating and freeing any resources by calling the proper operators.


Expressions and AltiVec

There are many caveats to be aware of when using AltiVec and writing your code. This section details information you need to effectively work with many popular expressions.

Most common C/C++ operators do not interoperate with the vector data type. The following sections describe extensions that have been made to accomodate AltiVec code.

The topics in this section are:


sizeof()

The sizeof() operator will return the value of 16 for the following usages:


main( void ) {
	vector unsigned int a;
	vector unsigned int *p;
	int i = (int) sizeof(a); // returns 16 for i
	int j = (int) sizeof(*p); // returns 16 for j
}


Assignment Operator

If either the left-hand side or the right-hand side of an expression has a vector type, both sides of the expression must be the same type. So this example is correct:


	vector unsigned int a = (vector unsigned int) 1;
	vector unsigned int b = (vector unsigned int) 2;
	
	a = b;

However, this would be an error:


	vector unsigned int a = (vector unsigned int) 1;
	vector float b = 2.09;
	
	a = b; // error


Address Operator

Using the address operator & works fine as long as it is applied to values of the correct (same) type. This is correct:


	vector unsigned int a = (vector unsigned int) 1;
	vector unsigned int *p;
	
	p = &a; // correct usage

This is incorrect usage because the address of the variable a does not contain the same type as p:


	vector unsigned int a = (vector unsigned int) 1;
	vector float *p;
	
	p = &a; // incorrect usage


Pointer Arithmetic

Most pointer arithmetic techniques work with AltiVec. To access a vector element in an array of vector data, this works fine:


vector unsigned int foo[4];
vector unsigned int *p = &foo;
vector unsigned int *q;
q = ++p;


Pointer Dereferencing

This can be somewhat tricky.

If p is a pointer to a vector type, then the value returned by *p is a 128-bit vector load operation from the address obtained by clearing the low-order bits of p. This is equivalent to vec_ld(0,p). A vector store would be accomplished by vec_st(0,p). If you want to mark the data as Least-Recently Used (LRU), the explicit instruction vec_ldl(0,p) or vec_st(int,type*) must be used.

Dereferencing a pointer to a non-vector type results in the standard behavior of either a load or copy of the corresponding type.

Accessing of non-aligned memory must be carried out explicitly by one of the following vec_ld( int,type*) operation, a vec_ldl(int,type*) operation, a vec_st(int,type*) operation or a vec_stl( int,type*) operations.


Type Casting

Pointers to both vector and non-vector quantities can be assigned to each other. If you apply a cast to a non-vector variable in an assignment to a vector quantity, you must ensure that you are assigning a 16-byte aligned value to the vector data type. By using a cast, you are implying that you know this to be true.

Casts from one vector type to another are provided using the usual C syntax:


long vector b = 0;
int unsigned vector a = (vector unsigned int) b;

The data in b is then converted to the vector a type without changing the bit pattern.


Vector Constants

You can use a vector constant wherever a vector data value is permitted. In other words, you can use a vector constant in a static or dynamic initializer, as a parameter to a function call, or in an assignment. The compiler generates code which either computes or loads the values into an AltiVec register.

The following forms are represented:


vector unsigned char

Represents a vector unsigned char constant consisting of a set of 16 unsigned 8-bit quantities, which all have the value specified by a single unsigned integer, or as individually specified by 16 unsigned integers.


(vector unsigned char)(unsigned int)(vector unsigned char)(unsigned int1...unsigned int16)


vector signed char

Represents a vector signed char constant consisting of a set of 16 signed 8-bit quantities, which all have the value specified by a single integer, or as individually specified by 16 integers.


(vector signed char)(signed int)(vector signed char)(signed int1...signed int16)


vector unsigned short

Represents a vector unsigned short constant consisting of a set of 8 unsigned 16-bit quantities, which all have the value specified by a single unsigned integer, or as individually specified by 8 unsigned integers.


(vector unsigned short)(unsigned int)(vector unsigned short)(unsigned int1...unsigned int8)


vector unsigned int

Represents a vector unsigned int constant consisting of a set of 4 unsigned 32-bit quantities, which all have the value specified by a single unsigned integer, or as individually specified by 4 unsigned integers.


(vector unsigned int)(unsigned int)(vector unsigned int)(unsigned int1...unsigned int4)


vector signed int

Represents a vector signed int constant consisting of a set of 4 signed 32-bit quantities, which all have the value specified by a single integer, or as individually specified by 4 integers.


(vector signed int)(int)(vector signed int)(int1...unsigned int4)


vector float

Represents a vector float constant consisting of a set of 4 32-bit floating-point quantities, which all have the value specified by a single float value, or as individually specified by 4 float values.


(vector float)(float)(vector float)(float1...unsigned float4)


Pointer Offsets

The table shown in Table 9.8 shows what happens when you apply the vec_step() operator to a type to determine the size of a given vector type.

This is illustrated by the following example:


vector float c;
int a = vec_step(c);
int b = vec_step(vector float);

A vector unsigned short type is considered to contain 8 unsigned 2-byte values. A pointer to unsigned 2-byte values used to index through an array of unsigned 2-byte values one full vector at a time should be incremented by vec_step(vector unsigned short), which gives a value of 8.

For a complete list of AltiVec vector types, refer to "AltiVec Vector Data Formats."

 

Expression
Value
vec_step(vector unsigned char)  
16  
vec_step(vector signed char)  
16  
vec_step(vector boolean char)  
16  
vec_step(vector unsigned short)  
8  
vec_step(vector signed short)  
8  
vec_step(vector boolean short)  
8  
vec_step(vector unsigned int)  
4  
vec_step(vector signed int)  
4  
vec_step(vector boolean int)  
4  
vec_step(vector float)  
4  
vec_step(vector pixel)  
8  

Values for Adjusting Pointers:

AltiVec-Specific Operators

The vector operators allow you to fully exploit the power of the AltiVec processors. A partial list of these operators is found in "AltiVec Intrinsics Support."

There are five different ways that these operators function:


Overloaded AltiVec Operation

This generates a vector instruction depending on the argument types. An example of this is vec_add(). The operand types are used to determine whether the operation is acceptable, to select a particular operation according to the types of the arguments, and to determine the type of the result.

For example,


vec_add(vector signed char, vector signed char); 

maps to vec_addubm() and returns a result of type vector signed char.

The following case maps onto vec_addubm() and returns a result of type vector unsigned short:


vec_add(vector unsigned short, vector unsigned short);

Each operator for an AltiVec operation requires a list of arguments representing the input operands, and returns a result. The permissible operand types for an AltiVec operation are restricted to those documented for the given operator. You can override these by explicitly casting the arguments to the correct type.


Specific AltiVec Operation

This is an operator that maps directly to an AltiVec instruction. An example of this is vec_addubm().

The operand types are used to determine whether an operation is valid and what the result type is. For example, this is valid:


vec_addubm(vector signed char, vector signed char); // valid

because it represents a reasonable way to do modular addition with signed bytes. This would produce a result in which saturation treats the operands as unsigned.

This is not valid:


vec_addubs(vector signed char, vector signed char); // not valid

This would produce a result in which adjacent pairs of signed bytes are treated as signed half words.


Predicate Operation

This is an operator that results in a 0 or 1, computed from an AltiVec operation. An example of this is vec_all_eq().


Casting Operators

Casting operations are discussed in "Type Casting."


Load Constant Operators

Loading a vector of constant components is discussed in "Vector Constants."


CR6 "Compare Dot" Instructions

The AltiVec operations that set condition register CR6 are treated somewhat differently. The programmer does not have access to specific register names. Instead of directly specifying a compare dot instruction, you reference a predicate that returns an integer value derived from the result of a compare dot instruction. This value can be used directly as a condition for branching.

The predicates all begin with vec_all_ or vec_any_. There are predicates to test the true and false state of any bit that can be set by a compare dot instruction. For example, vec_all_gt(p, q) tests the true value of bit 24 of the CR after executing some vcmpgt. instruction.

To complete the coverage by predicates, additional predicates exercise compare dot instructions with reversed or duplicated arguments. As examples, vec_all_lt(p,q) performs a vcmpgtx(q,p) and vec_all_nan(s) is mapped onto vcmpeqfp(p,p). If you want to have both the result of the compare dot instruction as returned in the vector register, and the value of CR6, you must specify two instructions.


Linker Issues

This section discusses the background information on the Mac OS linker and how it works. The topics in this section are:


Deadstripping Unused Code and Data

The PowerPC linker deadstrips unused code and data only from files compiled by the CodeWarrior C/C++ compiler. Assembler relocatable files and C/C++ object files built by other compilers are never deadstripped. Deadstripping is particularly useful for C++ programs. Libraries (archives) built with the CodeWarrior C/C++ compiler only contribute the used objects to the linked program. If a library has assembly or other C/C++ compiler built files, only those files that have at least one referenced object contribute to the linked program. Completely unreferenced object files are always ignored.


Stripping Resources

It is useful to know that 'ckid' resources are stripped, in addition to stripping 'mcvs' resources with ID=128. These are the version control resources used by Metrowerks Visual SourceSafe and MacCVSPro.


Link Order

Link order is generally specified in the Link Order view of the Project window. For general information on setting link order, see the IDE User Guide.

 


[ First ]  [ Previous ]  [ Next ]  [ Last ]  [ Manuals ]

Visit the Metrowerks website at: http://www.metrowerks.com
For assistance contact Metrowerks Technical Support at: cw_support@metrowerks.com
Copyright © 2000, Metrowerks Corp. All rights reserved.

Last updated: July 21, 2000