Powering Up
Volume Number: 10
Issue Number: 1
Column Tag: Powering Up
Moving to PowerPC
What do you need to get ready for Macintosh with PowerPC
By Richard Clark and Jordan Mattson, Apple Computer, Inc.
About your tour guides
For the next six months we will be serving as your tour guides, showing off the
work of some of the best talent at Apple Computer. Therefore, we thought that it was
appropriate to introduce ourselves to you:
Richard Clark - is a senior instructor and course designer in Apple’s Developer
University group. No stranger to new technologies, Richard spearheaded the System 7,
AppleScript, and PowerPC developer training projects, and is presently offering
PowerPC classes to Apple’s engineers and third-party developers.
Jordan Mattson - is a product marketing manager in Apple’s Developer Product’s
group. Jordan has been at Apple for seven years and in that time has been a product
manager for MacsBug, ResEdit, MPW, and now our PowerPC developer tools.
What is Powering up?
Welcome to Powering Up our new monthly column about preparing yourself and
your code for Apple’s next generation Macintosh® platform - Macintosh with
PowerPC™. In this column we will give you the straight scoop on Macintosh with
PowerPC, give you the information that you need to move your current applications to
the PowerPC processor-based systems, and give you the background to create new
applications that exploit the new features of the Macintosh with PowerPC.
Sometime in the first half of 1994, Apple Computer, Inc. will introduce
Macintosh with PowerPC: the next generation of Macintosh computers, based on RISC
technology, that will boost the base-level performance of Macintosh systems to two to
four times that of today’s high-end Quadras. And, while other computer companies are
relegating their RISC offerings to the high-end or to specific market niches, Apple will
drive PowerPC processor-based systems throughout the Macintosh product line. Our
intention is to, over time, convert from Macintosh with 68K to Macintosh with
PowerPC at every price point.
What is Macintosh with PowerPC?
Since the announcement of our intention to deliver Macintosh systems based on
PowerPC, there has been lots of misinformation and supposition circulating. If you
want to make yourself an instant expert on Macintosh with PowerPC, remember the
following:
• It’s a Macintosh - Because Macintosh with PowerPC is first and foremost a
Macintosh, almost everything that you know about programming Macintosh is
still true. This also means that it is extremely easy for you to move your
application over to Macintosh with PowerPC. A number of developers have been
able to port their major applications over to PowerPC in as little as two weeks
and have seen substantial performance improvements.
• Your software runs - Due to the high fidelity, high performance emulator
included in the system software of all Macintosh with PowerPC systems, today’s
68K applications run just fine, and run fast.
• New software flies - those developers that choose to make the move to PowerPC
will find that they are richly rewarded. The average application, without much
work on your part, can expect to enjoy a performance boost of 2 to 4 times what
you see on today’s high-end Quadras.
Making the move
In preparing yourself and your application for Macintosh with PowerPC, much of
this work can be done before you get your hands on development tools or a Macintosh
with PowerPC system. In the rest of this month’s column, we will give you an
overview of what is involved in preparing your source code to make the move to
Macintosh with PowerPC and tell you what you can do today to get ready.
Basic Macintosh Compatibility
While Macintosh with PowerPC is a Macintosh, the first step in making the move
to PowerPC is making sure that your application is faithfully following the Macintosh
compatibility guidelines that Apple has been preaching for years. While programs
could get away with a lot in the past, porting certain managers over to the PowerPC
architecture gave Apple's engineers a chance for a “clean start". Therefore, many of
the suggested compatibility rules are actually going to be enforced on Macintosh with
PowerPC.
The rules for ensuring your code will run on Macintosh with PowerPC are
essentially the same as those you’ve heard all along from Macintosh Developer
Technical Support. (The following discussion highlights some key points from
Technical Note M.OV 13 “10+ Commandments" by Rich Collyer and Dave Radcliffe,
and incorporates some additional PowerPC-specific information. In addition, more
information on programming for the PowerPC can be found in the self-paced
“Introduction to RISC and PowerPC” course available from APDA.)
• Minimize use of low memory
• Avoid writing to or reading from hardware directly
• Write 32-bit clean code
• Don't intermix data and code
• Avoid patching traps
There are a few new rules that apply to the new machines:
• Eliminate dependencies on 80- and 96-bit floating point
• Isolate dependencies on the runtime model
• Don't assume you know what's going to be fast
Low memory globals: Applications that use low-memory globals may no longer be
compatible when Apple revises the system software. This hinders Apple from adding
commonly requested features to the system and enhancing system performance.
Since some applications depend critically on the documented low-memory
globals, Apple is supplying a set of accessor calls for all documented low-memory
globals. (These calls are in a new set of C/C++ header files located on E.T.O. 12 and
coming soon to better development systems near you.) For compatibility reasons, the
accessors are implemented as macros on the 68K, but are implemented as actual
routines on Macintosh with PowerPC.
These accessor routines should be used now to replace explicit pointers to low
memory. However, this is not a license to use undocumented low-memory globals.
Apple makes no guarantee that these globals will continue to be available in future
system software releases.
Avoid writing to hardware: In addition to the low-memory locations used by the
operating system and Toolbox, the Macintosh often uses special addresses for
Memory-Mapped I/O. These addresses vary from Macintosh to Macintosh, and limit
your code to working with particular versions of the hardware.
Write 32-bit clean code: 68K Macintosh computers can be set to use only the
lower 24 bits of an address, for compatibility with the original 68000 addressing
model. In contrast, the PowerPC processor-based Macintosh computers will use all 32
bits of a memory address. Most developers have removed dependencies on 24-bit
addresses, but some are using the upper bit of an address for other purposes. If you are
doing this, be aware that your code is only 31-bit clean. It will not work on Macintosh
with PowerPC.
Don’t intermix data and code: The PowerPC runtime system may load native code
into a special read-only area. You should not include data either in your code or at the
end of your code, nor should you have self-modifying code. A future column will
discuss how the new runtime system supports static data (i.e. global variables) for all
code.
Avoid patching traps: Trap patches can impact the performance of a PowerPC
processor based Macintosh system due to some additional dispatching work that the
system has to perform. In addition, the new machines include special “split traps”
which incorporate separate versions tuned for the best performance when called from
emulation or when called from “native” code. These are traps that had no cause to be
patched in the past (such as AddPt), and will not be patchable in the future.
Eliminate dependencies on 80- and 96-bit floating point: The PowerPC processor
follows the IEEE 754 standard for floating-point arithmetic. In this standard, float is
32 bits, and double is 64 bits. (Apple has implemented a 128 bit “long double” type
in software for those applications which need the extra precision.) However, the
PowerPC Floating-Point Unit does not support Motorola’s 80/96-bit extended type.
Therefore, any code which depends on “extended” should be converted to one of the
hardware-supported types (for speed) or long double (for precision.)
Emulated code can use the 80 and 96-bit extended types via SANE, but the
emulator does not support direct calls to the 6888x FPU. Therefore, if you are porting
code which contains direct 6888x FPU calls, you should re-code using portable ANSI C.
Don’t be tempted to require that the user install a “software FPU” which will run
slower than SANE - do the right thing!
Isolate dependencies on runtime model: The existing runtime model contains many
features that are processor dependent or optimized for systems with extremely limited
memory. If your code depends on parts of the 68000 runtime architecture (such as
setting and restoring A5, examining the stack, or looking at the jump table entries),
you should try to eliminate this code, or at a minimum, wrap conditional compilation
directives around it.
Don’t assume you know what’s going to be fast: The new Macintosh with PowerPC
computers are being tuned for both compatibility and performance. Programs which
assume that 6888x-direct calls are faster than “standard” floating-point calls will
be in for a surprise, as will programs that assume that one particular toolbox call is
faster than another. Write your code to be as generic and compatible as possible, then
test it once you get your hands on the new systems.
Compiler Compatibility
With a new processor comes new compilers. And the new compiler from Apple, as
well as the compilers coming from third-parties, is a lot stricter than the 68K
compilers you are used to using. Therefore, you may need to spend some time
preparing your code for compilers which adhere more closely to the ANSI standards.
While the ultimate test will be re-compiling on the new PowerPC compilers, you
can learn much from your current compiler. THINK C users can use the “ANSI
Settings” button in the compiler options dialog to get a feel for what the new compilers
will be like. (When using the “ANSI compatibility” settings, turn “THINK C
extensions” back on so that the compiler will recognize the “pascal” keyword in the
Macintosh headers. Selecting “4 byte ints” is also a good idea, as this is the size used
by both the MPW and PowerPC compilers.) MPW users already have a fairly
ANSI-compliant compiler, though they should use the “-r” flag to detect calls to
undefined routines.)
In any case, running the MPW C and C++ compilers is a good benchmark to
illustrate what will and will not work on the PowerPC compilers. The MPW compiler
doesn’t implement THINK C’s “asm {}” directive, and neither does the PowerPC
compiler. (Such in-line assembly should be re-written as portable ANSI C, not just
moved into PowerPC assembler. You should only consider going to assembler after
testing the compiled code for performance.) MPW doesn’t use precompiled headers by
default, and the PowerPC compilers may not support them at all. MPW watches for
pointer assignment incompatibilities that THINK C passes by. In general, your code
will be more portable after running through two compilers than after running through
only one.
ANSI Compatibility
Just being able to survive the MPW compiler isn’t enough - your code has to
survive an ANSI-compliant compiler and a new runtime environment. Fortunately,
you can take three simple steps to improve your code’s portability and robustness:
• Don’t make assumptions about the size of an int
• Add function prototypes and self-prototyping functions
• Remove language extensions where you can
Don’t make assumptions about the size of an int: Portable C code should not make
assumptions about the size of an integer. For example, THINK C assumes int is 16 bits
unless you set the “4 byte ints” option. MPW and the current PowerPC compilers all
assume that int is 32 bits. Therefore, you should perform a global search for int in
your code and replace these references with something less compiler-specific. The
safest solution is to declare some “virtual types” such as a 16-bit int16 and a 32-bit
int32 in a special header. You can modify for each compiler and still retain
portability.
In general, you should use int only if you need the “natural” word size of the
machine, as you do for loop counters, array indices, and other values that are likely to
be manipulated in registers and that require efficient handling by the processor.
Add function prototypes and self-prototyping functions: Function prototypes are
an ANSI addition to the C language which allows the compiler to check (and potentially
coerce) the values being passed to and from a function. The PowerPC compilers, which
are true ANSI compilers, do a better job of type checking (and may be able to generate
better code) if you use declarations in this style. Adding function prototypes also
allows the compiler to catch potential parameter-passing errors at compile time
instead of allowing the debugger to catch them at runtime.
Remove language extensions where you can: The first step is to make your C code
as ANSI-compliant as possible, except for the “pascal” keyword, which is
Apple-specific, and "//" comments which are part of C++ but not ANSI C. All current
Macintosh C compilers (including PowerPC compilers) implement these language
extensions.
One major challenge that faces C++ programmers is the use of handle-based
objects. Handle-based objects are a non-ANSI extension to C++ that is not supported
by the PowerPC compilers. Therefore, you must change your code to use pointer-based
objects and update to a version of your class library that supports pointer-based
objects. (One advantage of this change is that it gives you access to C++'s full range of
features.)
Coming next month
We hope that this brief introduction to PowerPC development will help you begin
preparing your code for the next generation of Macintosh computers. In next month’s
column, we will give you are tour of the PowerPC processor architecture, give you a
taste of PowerPC assembly language, and show you why you won’t be writing much
assembly language in the future.