gcc PowerPC Assembly Quick Reference ("Cheat Sheet")

Instructions

Mnemonic
Purpose
Examples
li dest,const
Move the constant const into the register dest.  const can't be more than 16 bits long.
li %r3, 4
addis dest,const
Add the constant const<<16 to dest.
addis %r3, 0xf 
#   r3+=0xf0000
b label
"Branch".  Starts executing code at label.
b loop_start
bl func
"Branch and Link".  Saves return address in link register, then jumps to func. Used to call subroutines.  Be sure to save the link register to the stack first! (see stack example at right)
bl read_input
blr
"Branch to Link Register".  Jumps to lr.  Used to end a subroutine.
blr
lwz dest, off(ptr)
Load word from pointer.  dest=*(ptr+off); Copy the integer in memory at address off bytes from the ptr register into the dest register.
lwz %r3,8(%r4)
# Copy r3 from memory at 8 off r4
lwzu dest, off(ptr)
Load word with pointer update. dest=*(ptr+=off); Like lwz, but then changes the ptr register to equal ptr+off.
lwzu %r3,8(%r4) 
# Copy r3 from memory at 8 off r4; and add 8 to r4
stw src, off(ptr) Store word. *(ptr+off)=src;  There's also a "stwu" that does the pointer update like lwzu.
stw %r3,8(%r4) 
# Copy r3 to memory at 8 off r4
add dest, src1, src2
Add.  dest=src1+src2.  All three must be registers.  Register r0 is treated as if it has value zero, so "add %r3, %r5, %r0" is actually a move.
add %r3,%r3, %r4
addi dest, src, const
Add immediate.  dest=src+constsrc and dest are registers, const is an integer constant.
addi %r3, %r3, 0x42
mullw dest,src1,src2
dest=src1*src2.  There's a corresponding "mulhi" to get the high 32 bits of the product.
mullw %r3, %r3, %r4
cmp 0,0,a,b

Compare two values into condition register 0.  Sets flags that are used by the conditional jumps (below).
cmp 0,0,%r3, %r4
blt label Goto label if previous comparison came out as less-than.  Other conditionals available are: ble (<=), beq (==), bge (>=), bgt (>), and bne (!=). blt loop_again  # Jump if r3 < r4

Stack Frame

Example when using frame pointer and two local variables:
Contents
offset
saved link register
20(%r1)
ancient %r1
16(%r1)
Local variable 1
12(%r1)
Local variable 2 8(%r1)
(next link register)
4(%r1)
old %r1
0(%r1)

my_sub: # Adds 1 to first argument
  # Prologue
  stwu %r1,-16(%r1) # "push"
  mflr %r0  # r0 = link register
  stw %r0,20(%r1) # Save link register
  # Body of subroutine:
  addi %r3, %r3, 1
  # Epilogue
  lwz %r0,20(%r1)
  mtlr %r0
  addi %r1, %r1, 16 # "pop"
  blr

Constants, Registers, Memory

Constants can just be written normally.  HOWEVER, be aware that if an instruction expects a register, it'll treat "4" as a register number, not a constant!  Weirdness: if a constant is more than 16 bits long, you can't load it in one instruction.
Registers can actually just be written as a number, like "3" (meaning register r3).  To be clearer, preceed any register name with "%r"; for example, "%r3" means register r3.  This means "add 3,4,5" is the same as "add %r3, %r4, %r5".  Use the "i" (immediate) form of the instruction if you want to put in a constant, or use "li" to load the constant into a register.
All memory access is via the load and store routines--you *can't* just get to a random memory location from any instruction.

Registers

%r1 is the stack pointer
Return value in %r3
First 8 integer arguments are in %r3 through %r10; remainder on stack.
Free for use (no save needed):
   %r0, and %r3 through %r12
Must be saved:
   %r13 through %r31

Floating Point

Load and store from memory with lfs/lfd (load float single/double) stfs, stfd.
Arithmetic instructions start with "f", like "fadd", "fmul", "fmadd", "fdiv".  There are both single- and double-precision versions, with the single-precision versions ending in "s" (like fadds), but they both use the same register set.
Weird instructions: "fres" (computes approximate 1.0/x); "frsqrte"  (1.0/sqrt(x), approximate).

Floating Point Registers

Registers are all 64-bit doubles.
Floating point args are in %f1-%f13
 %f0-%f13 are free for any use
%f14-%f31 must be saved
Return value goes in %f1

Common Errors

Error: operand out of range (123 not between 0 and 31)
   You passed in some constant (here 123); the assembler expected a register.
Error: operand out of range (100000 not between -32768 and 32767)
   You passed in a constant that was too big.  Use "li" and "addis" to stick the constant together from 16-bit pieces (or just choose another constant!)


The IBM 32-Bit PowerPC Programming Environment gives all the instructions in chapter 8.1 and a good overview in chapter 4.  The IBM Compiler Writer's Guide gives the calling conventions.


O. Lawlor, ffosl@uaf.edu
Up to: Class Site, CS, UAF