PowerPC Assembly Cheatsheet
Instructions, registers and general info cheatsheet for PowerPC 32-bit Big Endian Assembly architecture used by the Wii U.
How to read this cheatsheet
- 64-bit only instructions and behaviors are entirely ignored and removed from this cheatsheet.
- If a right shift operation does not specify it is sign-fill, it is implicitly zero-fill by default
- If a value is referred to simply as "value" without specifying bit-count, it is implicitly 32 bits (aka a WORD, integer or float depending on context)
- Multiplications and divisions implicitly result in a 64-bit value
- C-style casts are used due to being shorter to fit in the small table cells code snippets, but treat them as static_cast<T>
- The pseudocode examples are a C++ code representation to visualize the logic of an instruction, it is NOT code that compiles down to that instruction!
- In most cases where "float" is mentioned in a sentence (not a code snippet where it refers to the type), it usually means "a floating point value" which can be either float or double, not only float.
- # = placeholder (either a number or a letter, a letter is a labelled placeholder for a number so it may be referenced to by other text)
- r# = register (shorthand for GPR#)
- f# = floating point register (shorthand for FPR#)
- i# = immediate (the subscript numbers next to it is it's size in bits)
- ui# = unsigned immediate (above is signed)
- Instruction parameters wrapped in square brackets (
[example]
) are optional and can be omitted. - * = unsure of exact functionality
- "Assembly-only" instructions do NOT mean they cannot be generated from C++ compilation but rather they have no direct C++ snippet equivalent and instead are "glue" required to make the processor work.
typedef unsigned int uint; // 32 bit integer value
typedef signed int sint; // 32 bit integer value
typedef unsigned short ushort; // 16 bit integer value
typedef signed short sshort; // 16 bit integer value
typedef unsigned char ubyte; // 8 bit integer value
typedef signed char sbyte; // 8 bit integer value
float; // 32 bit floating point value
double; // 64 bit floating point value
|
---|
Register | Name | Attributes | Bits | Purpose |
---|---|---|---|---|
General Purpose Registers (GPRs) | ||||
r0 | GPR0 | Volatile + Cross-Module | 32 | General purpose, may be used by function linkage |
r1 | GPR1 | Saved + Reserved | 32 | Reserved for storing the stack frame pointer |
r2 | GPR2 | Reserved | 32 | Reserved for usage by the system |
r3 | GPR3 | Volatile | 32 | Stores 1st argument passed to function calls and their return value |
r4 - r10 | GPR4 - GPR10 | Volatile | 32 | Store from 2nd to 8th argument passed to function calls |
r11 - r12 | GPR11 - GPR12 | Volatile + Cross-Module | 32 | General purpose, may be used by function linkage |
r13 | GPR13 | Reserved | 32 | Reserved for storing the small data area (SDA) pointer |
r14 - r31 | GPR14 - GPR31 | Saved | 32 | General purpose, store generic integer values and pointers |
Floating Point Registers (FPRs) | ||||
f0 | FPR0 | Volatile | 64 | Store generic floating point numbers |
f1 | FPR1 | Volatile | 64 | Stores 1st float argument passed to function calls and their float return value |
f2 - f8 | FPR2 - FPR8 | Volatile | 64 | Store from 2nd to 8th float argument passed to function calls |
f9 - f13 | FPR9 - FPR13 | Volatile | 64 | Store generic floating point numbers |
f14 - f30 | FPR14 - FPR30 | Saved | 64 | Store generic floating point numbers |
f31 | FPR31 | Saved | 64 | General purpose, used for static chain if needed |
Special Purpose Registers (SPRs) | ||||
PC / IAR | Program Counter / Instruction Address Register | Internal | 32 | Stores the address of the current instruction (Controlled by the CPU) |
LR | Link Register | Volatile | 32 | Stores the return address for some of the branching instructions |
CTR | CounT Register | Volatile | 32 | Stores the counter of loop iterations for most instructions that perform loops. Also used for virtual function calls as it can contain an address which can be branched to |
MSR | Machine State Register | Special | 32 | Stores bits with information about the CPU and its current state |
SRR0 | machine status Save/Restore Register 0 | Interrupt-only | 32 | When an exception occurs, holds the address where instruction processing should resume when the exception handler returns control to the interrupted process |
SRR1 | machine status Save/Restore Register 1 | Interrupt-only | 32 | Stores machine status (select MSR bits and possibly other status bits as well) on exceptions, in order to restore those values when an rfi instruction is executed
|
CR | Condition Register | Volatile / Saved | 32 | Divided in 8 bitfields of 4 bits each to hold different kinds of conditions |
XER | fiXed point Exception Register | Volatile | 32 | Indicates overflows and carry conditions for integer operations and the number of bytes to be transferred by the load/store string indexed instructions |
FPSCR | Floating Point Status and Control Register | Volatile | 32 | Contains all floating point exception signal bits, exception summary bits, exception enable bits, and rounding control bits needed for compliance with the IEEE754 floating point arithmetic standard |
TB | Time Base | Special | 64 | Maintains the time of day and operates interval timers. The TB is not a register itself but the combined value of the two 32-bit registers TBU and TBL. |
... | There are way more but less common SPRs which won't be listed here | - | - | For a full but undescriptive list of all SPRs, visit wiiubrew.org/Hardware/Espresso |
Instruction | Name | Parameters | Pseudocode Equivalent[1] | Additional Info |
---|---|---|---|---|
Integer Arithmetic Instructions | ||||
add [2][3]
|
ADD operation | rA, rB, rC
|
rA = rB + rC
|
Adds the values of rB and rC together and stores the result in rA |
addc [2][3]
|
ADD Carrying | rA, rB, rC
|
rA = rB + rC
|
Adds the values of rB and rC together and stores the result in rA |
addi
|
ADD Immediate | rA, rB, iX₁₆
|
rA = rB + iX
|
Adds the values of rB and iX together and stores the result in rA |
addic [2]
|
ADD Immediate Carrying | rA, rB, iX₅
|
rA = rB + iX
|
Adds the values of rB and iX together and stores the result in rA |
addis
|
ADD Immediate Shifted | rA, rB, iX₁₆
|
rA = rB + (iX << 16)
|
Adds the values of rB and (iX << 16) together and stores the result in rA |
adde [2][3]
|
ADD Extended | rA, rB, rC
|
rA = rB + rC + XER[CA]
|
Adds the values of rB, rC and XER[CA] together and stores the result in rA |
addme [2][3]
|
ADD to Minus one Extended | rA, rB
|
rA = rB + XER[CA] + 0xFFFFFFFF
|
Adds the values of rB, XER[CA] and 0xFFFFFFFF together and stores the result in rA |
addze [2][3]
|
ADD to Zero Extended | rA, rB
|
rA = rB + XER[CA]
|
Adds the values of rB and XER[CA] together and stores the result in rA |
subf [2][3]
|
SUBtract From | rA, rB, rC
|
rA = rC - rB
|
Subtracts the value of rB from rC and stores the result in rA. |
subfc [2][3]
|
SUBtract From, Carrying | rA, rB, rC
|
rA = rC - rB
|
Subtracts the value of rB from rC and stores the result in rA. |
subfic
|
SUBtract From Immediate Carrying | rA, rB, iX₅
|
rA = iX - rB
|
Subtracts the value of iX from rC and stores the result in rA. (CRO is modified) |
subfe [2][3]
|
SUBtract From, Extended | rA, rB, rC
|
rA = (rC - rB) + XER[CA]
|
Subtracts the value of rB from rC and adds the value of XER[CA] to the result, then stores the final result in rA |
subfme [2][3]
|
SUBtract From Minus one Extended | rA, rB
|
rA = (XER[CA] - rB) + 0xFFFFFFFF
|
Subtracts the value of rB from XER[CA], adds 0xFFFFFFFF to the result, then stores the final result in rA |
subfze [2][3]
|
SUBtract From Zero Extended | rA, rB
|
rA = XER[CA] - rB
|
Subtracts the value of rB from XER[CA] and stores the result in rA |
neg [2][3]
|
NEGate | rA, rB
|
rA = 1 - rB
|
Subtracts the value of rB from 1 and stores the result in rA |
mulli
|
MULtiply Low Immediate | rA, rB, iX₁₆
|
rA = (rB * iX) & 0xFFFFFFFF
|
Multiplies the value of rB by iX and stores the lower 32 bits of the result in rA |
mullw [2][3]
|
MULtiply Low Word | rA, rB, rC
|
rA = (rB * rC) & 0xFFFFFFFF
|
Multiplies the value of rB by the value of rC and stores the lower 32 bits of the result in rA |
mulhw [2]
|
MULtiply High Word | rA, rB, rC
|
rA = (rB * rC) >> 32
|
Multiplies the value of rB by the value of rC and stores the upper 32 bits of the result in rA |
mulhwu [2]
|
MULtiply High Word Unsigned | rA, rB, rC
|
rA = ((uint)rB * (uint)rC) >> 32
|
Multiplies the unsigned value of rB by the unsigned value of rC and stores the upper 32 bits of the result in rA |
divw [2][3]
|
DIVide Word | rA, rB, rC
|
rA = rB / rC
|
Divides the value of rB by the value of rC and stores the result in rA. The remainder is lost. |
divwu [2][3]
|
DIVide Word Unsigned | rA, rB, rC
|
rA = (uint)rB / (uint)rC
|
Divides the unsigned value of rB by the unsigned value of rC and stores the result in rA. The remainder is lost. |
Integer Comparison Instructions | ||||
| ||||
cmp
|
CoMPare | [cr#,] 0, rA, rB
|
N/A | The value of rA is compared to the value of rB, the results of the comparison are stored in cr# |
cmpi
|
CoMPare Immediate | [cr#,] 0, rA, iX
|
N/A | The value of rA is compared to iX, the results of the comparison are stored in cr# |
cmpl
|
CoMPare Logical | [cr#,] 0, rA, rB
|
N/A | The unsigned value of rA is compared to the unsigned value of rB, the results of the comparison are stored in cr# |
cmpli
|
CoMPare Logical Immediate | [cr#,] 0, rA, uiX
|
N/A | The unsigned value of rA is compared to uiX, the results of the comparison are stored in cr# |
cmpw
|
CoMPare Word | rA, rB
|
N/A | |
cmpwi
|
CoMPare Word Immediate | rA, iX₁₆
|
N/A | |
cmplwi
|
CoMPare Logical Word Immediate | N/A | ||
Integer Logical Instructions | ||||
andi.
|
AND Immediate | rA, rB, uiX₁₆
|
rA = rB & uiX
|
Performs an AND operation on rB and uiX then stores the result in rA |
andis.
|
AND Immediate Shifted | rA, rB, uiX₁₆
|
rA = rB & (uiX << 16)
|
Performs an AND operation on rB and (uiX << 16) then stores the result in rA |
ori
|
OR Immediate | rA, rB, iX₁₆
|
rA = rB | iX
|
Stores in rA the result of (rB | iX) |
oris
|
OR Immediate Shifted | rA, rB, iX₁₆
|
rA = rB | (iX << 16)
|
Stores in rA the result of (rB | (iX << 16)) |
xori
|
XOR Immediate | rA, rB, iX₁₆
|
rA = rB ^ iX
|
Performs an XOR operation on rB and iX then stores the result in rA |
xoris
|
XOR Immediate Shifted | rA, rB, iX₁₆
|
rA = rB ^ (iX << 16)
|
Performs an XOR operation on rB and (iX << 16) then stores the result in rA |
and [2]
|
AND Operation | rA, rB, rC
|
rA = rB & rC
|
Performs an AND operation on rB and rC then stores the result in rA |
or [2]
|
OR operation | rA, rB, rC
|
rA = rB | rC
|
Stores in rA the result of (rB | rC) |
xor [2]
|
XOR operation | rA, rB, rC
|
rA = rB ^ rC
|
Performs an XOR operation on rB and rC then stores the result in rA |
nand [2]
|
NAND operation | rA, rB, rC
|
rA = ~(rB & rC)
|
Stores in rA the negated result of (rB & rC) |
nor [2]
|
NOR operation | rA, rB, rC
|
rA = ~(rB | rC)
|
Stores in rA the negated result of (rB | rC) |
eqv *[2]
|
EQuiValent | rA, rB, rC
|
rA = rB == rC
|
Compares if the values of rB and rC are equal and stores the result in rA (?) |
andc [2]
|
AND Complement | rA, rB, rC
|
rA = rB & ~rC
|
Performs an AND operation on rB and negated rC then stores the result in rA |
orc [2]
|
OR Complement | rA, rB, rC
|
rA = rB | ~rC
|
Stores in rA the result of (rB | ~rC) |
extsb [2]
|
EXTend Sign Byte | rA, rB
|
rA = (int8_t)rB
|
Fills the upper 24 bits of rB's value with the sign bit of the stored 8 bit value |
extsh [2]
|
EXTend Sign Halfword | rA, rB
|
rA = (int16_t)rB
|
Fills the upper 16 bits of rB's value with the sign bit of the stored 16 bit value |
cntlzw [2]
|
CouNT Leading Zeros Word | rA, rB
|
N/A | Stores into rA the number of consecutive leading zero bits in the value of rB |
Integer Rotate Instructions | ||||
rlwinm [2]
|
Rotate Left Word Immediate, aNd with Mask | rA, rB, iX₅, iY₅, iZ₅
|
uint mask = ((uint)-1) << (31 - iZ + iY) >> iY;
rA = (rB << iX) | (rB >> (32 - iX)) & mask;
|
Rotates the value in rB by iX bits to the left
The result of the above is AND'ed with the mask specified by iY and iZ iY specifies the starting bit of the 1-bits in the mask (0-indexed) iZ specifies the end bit of the 1-bits in the mask (0-indexed) The final result is stored in rA |
rlwnm [2]
|
Rotate Left Word, aNd with Mask | |||
rlwimi [2]
|
Rotate Left Word Immediate, Mask Insert | |||
Integer Shift Instructions | ||||
slw [2]
|
Shift Left Word | rA, rB, rC
|
rA = rB << rC
|
Shifts the value in rB by the value in rC to the left and stores the result in rA |
srw [2]
|
Shift Right Word | rA, rB, rC
|
rA = (unsigned)rB >> rC
|
Shifts the value in rB by the value in rC to the right and stores the result in rA |
srawi [2]
|
Shift Right Algebraic Word Immediate | rA, rB, iX₅
|
rA = (signed)rB >> iX
|
Shifts the value in rB by iX to the right and stores the result in rA
Unlike regular zero-fill right shift operations, this one sign-fills the vacant bits |
sraw [2]
|
Shift Right Algebraic Word | rA, rB, rC
|
rA = (signed)rB >> rC
|
Shifts the value in rB by the value in rC to the right and stores the result in rA
Unlike regular zero-fill right shift operations, this one sign-fills the vacant bits |
slwi
|
Shift Left Word Immediate | rA, rB, iX₅
|
rA = rB << iX
|
Shifts the value in rB by iX to the left and stores the result in rA |
srwi
|
Shift Right Word Immediate | rA, rB, iX₅
|
rA = (unsigned)rB >> iX
|
Shifts the value in rB by iX to the right and stores the result in rA |
Floating Point Arithmetic Instructions | ||||
Floating Point Multiply-Add Instructions | ||||
Floating Point Rounding & Conversion Instructions | ||||
Floating Point Comparison Instructions | ||||
Floating Point Status and Control Register Instructions | ||||
Floating Point Move Instructions | ||||
fmr [2]
|
Float Move Register | fA, fB
|
fA = fB
|
Copies the value of fB into fA (Despite the instruction name, fB is preserved) |
fneg [2]
|
Float Negate | fA, fB
|
fA = -fB
|
Negates the value of fB and stores the result in fA |
fabs [2]
|
Float Absolute | fA, fB
|
fA = abs(fB)
|
The absolute value of fB is stored into rA |
fnabs [2]
|
Float Negative Absolute | fA, fB
|
fA = -abs(fB)
|
The negative absolute value of fB is stored into rA |
Floating Point Load Instructions | ||||
lfs
|
Load Float Single | fA, iX₁₆(rA)
|
fA = (float)(*(rA + iX))
|
Loads the value at the address (rA + iX) casted to float into fA. |
lfsx
|
Load Float Single indeXed | |||
lfsu
|
Load Float Single Update | |||
lfsux
|
Load Float Single Update indeXed | |||
lfd
|
Load Float Double | fA, iX₁₆(rA)
|
fA = (double)(*(rA + iX))
|
Loads the 64 bit value at the address (rA + iX) casted to double into fA. |
lfdx
|
Load Float Double indeXed | |||
lfdu
|
Load Float Double Update | |||
lfdux
|
Load Float Double Update indeXed | |||
Floating Point Store Instructions | ||||
stfs
|
STore Float Single | fA, iX₁₆(rA)
|
*(rA + iX) = (float)fA
|
Stores the value of fA casted to float at the memory address (rA + iX) |
stfsx
|
STore Float Single indeXed | |||
stfsu
|
STore Float Single Update | |||
stfsux
|
STore Float Single Update indeXed | |||
stfd
|
STore Float Double | fA, iX₁₆(rA)
|
*(rA + iX) = fA
|
Stores the 64 bit value of fA at the memory address (rA + iX) |
stfdx
|
STore Float Double indeXed | |||
stfdu
|
STore Float Double Update | |||
stfdux
|
STore Float Double Update indeXed | |||
stfiwx
|
STore Float as Integer Word indeXed | |||
Paired Singles Instructions (WIP)[4] | ||||
psq_l
|
Paired Single Quantized Load | |||
psq_lx
|
Paired Single Quantized Load indeXed | |||
psq_lu
|
Paired Single Quantized Load Update | |||
psq_lux
|
Paired Single Quantized Load Update indeXed | |||
psq_st
|
Paired Single Quantized Store | |||
psq_stx
|
Paired Single Quantized Store indeXed | |||
psq_stu
|
Paired Single Quantized Store Update | |||
psq_stux
|
Paired Single Quantized Store Update indeXed | |||
ps_abs
|
Paired Single ABSolute | |||
ps_add
|
Paired Single ADD | |||
ps_cmpo0
|
Paired Single CoMPare Ordered high(0) | |||
ps_cmpo1
|
Paired Single CoMPare Ordered low(1) | |||
ps_cmpu0
|
Paired Single CoMPare Unordered high(0) | |||
ps_cmpu1
|
Paired Single CoMPare Unordered low(1) | |||
ps_div
|
Paired Single DIVide | |||
ps_madd
|
Paired Single Multiply & ADD | |||
ps_madds0
|
Paired Single Multiply & ADD Scalar high(0) | |||
ps_madds1
|
Paired Single Multiply & ADD Scalar low(1) | |||
ps_merge00
|
Paired Single MERGE high(00) | |||
ps_merge01
|
Paired Single MERGE direct(01) | |||
ps_merge10
|
Paired Single MERGE swapped(10) | |||
ps_merge11
|
Paired Single MERGE low(11) | |||
ps_mr
|
Paired Single Move Register | |||
ps_msub
|
Paired Single Multiply & SUBtract | |||
ps_mul
|
Paired Single MULtiply | |||
ps_muls0
|
Paired Single MULtiply Scalar high(0) | |||
ps_muls1
|
Paired Single MULtiply Scalar low(1) | |||
ps_nabs
|
Paired Single Negative ABSolute | |||
ps_neg
|
Paired Single NEGate | |||
ps_nmadd
|
Paired Single Negative Multiply & ADD | |||
ps_nmsub
|
Paired Single Negative Multiply & SUBtract | |||
ps_res
|
Paired Single Reciprocal EStimate | |||
ps_rsqrte
|
Paired Single Reciprocal SQuareRooT Estimate | |||
ps_sel
|
Paired Single SELect | |||
ps_sub
|
Paired Single SUBtract | |||
ps_sum0
|
Paired Single vector SUM high(0) | |||
ps_sum1
|
Paired Single vector SUM low(1) | |||
Integer Load Instructions | ||||
lbz
|
Load Byte Zero-fill | rA, iX₁₆(rB)
|
rA = (ubyte)(*(rB + iX))
|
Loads the 8 bit value at the address (rB + iX) into rA |
lbzx
|
Load Byte Zero-fill indeXed | |||
lbzu
|
Load Byte Zero-fill Update | |||
lbzux
|
Load Byte Zero-fill Update indeXed | |||
lhz
|
Load Halfword Zero-fill | rA, iX₁₆(rB)
|
rA = (ushort)(*(rB + iX))
|
Loads the 16 bit value at the address (rB + iX) into rA |
lhzx
|
Load Halfword Zero-fill indeXed | |||
lhzu
|
Load Halfword Zero-fill Update | |||
lhzux
|
Load Halfword Zero-fill Update indeXed | |||
lha
|
Load Halfword Algebraic | rA, iX₁₆(rB)
|
||
lhax
|
Load Halfword Algebraic indeXed | |||
lhau
|
Load Halfword Algebraic Update | |||
lhaux
|
Load Halfword Algebraic Update indeXed | |||
lwz
|
Load Word Zero-fill | rA, iX₁₆(rB)
|
rA = *(rB + iX)
|
Loads the value at the address (rB + iX) into rA |
lwzx
|
Load Word Zero-fill indeXed | rA, rB, rC
|
rA = *(rB + rC)
|
Loads the value at the address (rB + rC) into rA |
lwzu
|
Load Word Zero-fill Update | rA, iX₁₆(rB)
|
rA = *(rB + iX);
rB = rB + iX;
|
Loads the value at the address (rB + iX) into rA Then loads rB with the address (rB + iX) |
lwzux
|
Load Word Zero-fill Update indeXed | |||
lmw *
|
Load Multiple Words | rA, iX₁₆(rB)
|
int EA = rB + iX;
int N = rA;
do {
GPR[N] = *(EA);
EA = EA + 4;
N = N + 1;
} while (N <= 31);
|
Loads GPR[rA] to r31 with the value at the address (rB + iX + N),
where N starts at 0 and increments by 4 for each register loaded.
|
Integer Store Instructions | ||||
stb
|
STore Byte | rA, iX₁₆(rB)
|
*(rB + iX) = (ubyte)rA
|
Stores the 8 bit value of rA at the memory address (rB + iX) |
stbx
|
STore Byte indeXed | |||
stbu
|
STore Byte Update | |||
stbux
|
STore Byte Update indeXed | |||
sth
|
STore Halfword | rA, iX₁₆(rB)
|
*(rB + iX) = (ushort)rA
|
Stores the 16 bit value of rA at the memory address (rB + iX) |
sthx
|
STore Halfword indeXed | |||
sthu
|
STore Halfword Update | |||
sthux
|
STore Halfword Update indeXed | |||
stw
|
STore Word | rA, iX₁₆(rB)
|
*(rB + iX) = rA
|
Stores the value of rA at the memory address (rB + iX) |
stwx
|
STore Word indeXed | rA, rB, rC
|
*(rB + rC) = rA
|
Stores the value of rA at the memory address (rB + rC) |
stwu
|
STore Word And Update | rA, iX₁₆(rB)
|
*(rB + iX) = rA
|
Stores the value of rA at the memory address (rB + iX)
Stores the computed address (rB + iX) into rB |
stwux
|
STore Word And Update indeXed | rA, rB, rC
|
||
stmw *
|
STore Multiple Words | |||
Little Endian Integer Load & Store Instructions | ||||
Integer Load and Store Strings Instructions | ||||
Branch Instructions | ||||
b
|
Branch | iX₂₄
|
goto LABEL
|
Jumps from the current address to IAR + iX, either up or down |
ba
|
Branch Absolute | iX₂₄
|
goto LABEL
|
Jumps from the current address to the address iX, either up or down |
bl
|
Branch & Link | iX₂₄
|
((void (*)())IAR + iX)()
|
Jumps from the current address to IAR + iX, either up or down
Also stores the address of the instruction directly below itself in LR This is the most common instruction used for calling a function |
bla
|
Branch & Link Absolute | iX₂₄
|
((void (*)())IAR + iX)()
|
Jumps from the current address to the address iX, either up or down
Also stores the address of the instruction directly below itself in LR |
bc
|
Branch Conditional | BO, BI, iX
|
||
bca
|
Branch Conditional Absolute | BO, BI, iX
|
||
bcl
|
Branch Conditional & Link | BO, BI, iX
|
||
bcla
|
Branch Conditional & Link Absolute | BO, BI, iX
|
||
bclr
|
Branch Conditional to Link Register | BO, BI, BH
|
||
bclrl
|
Branch Conditional to Link Register & Link | BO, BI, BH
|
||
bcctr
|
Branch Conditional to CounT Register | BO, BI, BH
|
||
bcctrl
|
Branch Conditional to CounT Register & Link | BO, BI, BH
|
||
blr
|
Branch to Link Register | N/A | return <r3 / f1>
|
Jumps from the current address to the address stored in LR
This is essentially the return statement of a function, with the value currently loaded into either r3 or f1 holding the returned value, depending on if the return type is a fixed or floating point value |
beq
|
Branch if EQual | iX₂₄
|
if (x == y) goto LABEL
|
If the EQ bit in CR0 is 1, jumps from the current address to IAR + iX
Otherwise, does nothing |
bne
|
Branch if Not Equal | iX₂₄
|
if (x != y) goto LABEL
|
If the EQ bit in CR0 is 0, jumps from the current address to IAR + iX
Otherwise, does nothing |
bgt
|
Branch if Greater Than | iX₂₄
|
if (x > y) goto LABEL
|
If the GT bit in CR0 is 1, jumps from the current address to IAR + iX
Otherwise, does nothing |
blt
|
Branch if Less Than | iX₂₄
|
if (x < y) goto LABEL
|
If the LT bit in CR0 is 1, jumps from the current address to IAR + iX
Otherwise, does nothing |
bge
|
Branch if Greater than or Equal | iX₂₄
|
if (x >= y) goto LABEL
|
If either the GT bit or EQ bit in CR0 is 1, jumps from the current address to IAR + iX
Otherwise, does nothing |
ble
|
Branch if Less than or Equal | iX₂₄
|
if (x <= y) goto LABEL
|
If either the LT bit or EQ bit in CR0 is 1, jumps from the current address to IAR + iX
Otherwise, does nothing |
bng
|
Branch if Not Greater than | |||
bnl
|
Branch if Not Less than | |||
bso
|
Branch if Summary Overflow | ??? | ??? | ??? |
bns
|
Branch if Not Summary overflow | ??? | ??? | ??? |
bun
|
Branch if UNordered | ??? | ??? | ??? |
bnu
|
Branch if Not Unordered | ??? | ??? | ??? |
bctr
|
Branch to CounT Register | |||
bctrl
|
Branch to CounT Register and Link | |||
bdnz
|
Branch if Decremented count register Not Zero | |||
bdnzt
|
Branch if Decremented count register Not Zero and if condition True | |||
bdnzf
|
Branch if Decremented count register Not Zero and if condition False | |||
bdz
|
Branch if Decremented count register Zero | |||
Condition Register Logical Instructions | ||||
Move to/from Special Purpose Registers Instructions | ||||
mflr
|
Move From Link Register | rA
|
rA = LR
|
Copies the value of LR into rA |
mtlr
|
Move To Link Register | rA
|
LR = rA
|
Copies the value of rA into the LR |
mtctr
|
Move To CounT Register | rA
|
CTR = rA
|
Copies the value of rA into the CTR |
mtfsf *
|
Move To FpScr Fields | UNK1, fA
|
??? | Copies the value of fA into the FPSCR under the control of the field mask in UNK1 |
mtfsb1
|
Move To FpScr Bit 1 | iX?
|
FPSCR = FPSCR | 0b1 << iX - 1
|
Sets bit iX of the FPSCR register to 1 |
mtspr
|
Move To Special Purpose Register | SPR, rA
|
SPRs[SPR] = rA
|
Copies the value of rA into the special purpose register SPR |
mfspr
|
Move From Special Purpose Register | rA, SPR
|
rA = SPRs[SPR]
|
Copies the value of special purpose register SPR into rA |
mfmsr
|
Move From Machine State Register | rA
|
rA = MSR
|
Copies the value of MSR into rA |
mftb
|
Move From Time Base | rA [, TBR]
|
N/A | If TBR == 268, the value of TBL (Time Base Lower) is copied into rA
If TBR == 269, the value of TBU (Time Base Upper) is copied into rA If TBR is omitted, 268 is used as default value |
mftbu
|
Move From Time Base Upper | rA
|
N/A | Copies the value of TBU (Time Base Upper) into rA |
Trap Instructions | ||||
twi
|
Trap Word Immediate | TO, rA, iX
|
||
tw
|
Trap Word | TO, rA, rB
|
||
Memory Synchronization Instructions | ||||
lwarx
|
Load Word And Reserve indeXed | rA, rB, rC
|
||
stwcx.
|
STore Word Conditional indeXed | rA, rB, rC
|
||
sync
|
SYNChronize | L
|
Assembly-only instruction | Delays all following instructions until all previous instructions required for context are complete. |
eieio
|
Enforce In-order Execution of I/O | N/A | Assembly-only instruction | "Provides an ordering function for the effects of loads and stores executed by the processor." |
isync
|
Instruction SYNChronize | N/A | Assembly-only instruction | Delays all following instructions until all previous instructions required for context are complete.
Additionally discards all prefetched instructions for a context reset. |
Cache Control Instructions | ||||
dcbz_l
|
Data Cache Block Zero and Lock | rA, rB
|
Assembly-only instruction | Too complex.[5]All you might need to know about this instruction is rA+rB form an address input, and it does not modify any registers. |
dcbi
|
Data Cache Block Invalidate | rA, rB
|
Assembly-only instruction | Too complex.[5] |
External Control Instructions | ||||
eciwx
|
External Control In Word indeXed | rA, rB, rC
|
||
ecowx
|
External Control Out Word indeXed | rA, rB, rC
|
||
Uncategorized instructions (categories WIP) | ||||
li
|
Load Immediate | rA, iX₁₆
|
rA = iX
|
Loads iX into rA |
lis
|
Load Immediate Shifted | rA, iX₁₆
|
rA = rA | (iX << 16)
|
Loads iX into the upper 16 bits of rA |
la
|
Load Address | rA, iX₁₆(rB)
|
rA = rB + iX
|
Adds iX to the address stored in rB and loads the result into rA. |
mr [2]
|
Move Register | rA, rB
|
rA = rB
|
Copies the value of rB into rA (Despite the instruction name, rB is preserved) |
not
|
NOT operation | rA, rB
|
rA = ~rB
|
Stores in rA the result of negated rB |
Misc. Instructions | ||||
nop
|
No OPeration | N/A | ;
|
Does nothing |
sc
|
System Call | [iX₇]
|
N/A | Calls upon the system to perform a service identified by iX
If iX is not provided, triggers a system call exception. |
rfi
|
Return From Interrupt |
External Resources
- http://class.ece.iastate.edu/arun/CprE281_F05/lab/labw10a/Labw10a_Files/PowerPC%20Assembly%20Quick%20Reference.htm (few but nicely explained instructions with some examples and explains a little about assembly source files)
- https://jimkatz.github.io/powerpc_for_dummies (very incomplete, has mistakes)
- http://wiibrew.org/wiki/Assembler_Tutorial (also has missing instructions but way more accurate and better worded)
- https://fail0verflow.com/media/files/ppc_750cl.pdf (official instruction set docs, hard to navigate/search)
- http://personal.denison.edu/~bressoud/cs281-s07/ppc_instructions.pdf (similar to the above but stripped of all pages not documenting instructions, easier to search, missing instructions and references)
- @archive:https://wiki.alcf.anl.gov/images/f/fb/PowerPC_-_Assembly_-_IBM_Programming_Environment_2.3.pdf (additional instructions not included in the official instruction set docs, instead it points to this document)
- https://www.nxp.com/docs/en/application-note/AN2491.pdf (similar to the above but stripped of all pages not related to instructions, easier to search, also specific to 32 bit unlike the main document)
- http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf (the PowerPC ELF specification, contains some advanced in-depth information about the processor and thus its assembly mechanics)
- http://www.csit-sun.pub.ro/~cpop/Documentatie_SMP/Motorola_PowerPC/PowerPc/GenInfo/pemch2.pdf (general PowerPC architecture information spec, good advanced registers reference)
- https://smashboards.com/threads/guide-using-paired-singles-and-gqrs.456834/ (paired singles tutorial, has some nice visual instruction graphs)
- https://mariokartwii.com/showthread.php?tid=1870 (another paired singles tutorial, very Wii-oriented but much of the same still applies in Wii U)
- https://www.nxp.com/docs/en/application-note/AN2491.pdf (more ppc docs, see chapter 4.3 Incorporating the BO Branch Prediction for branch prediction info (the + and - suffixes that may appear in conditional branch instructions))
- ↑ These code snippets DO NOT necessarily compile to exactly the given instruction, but rather are a C++ syntax-like representation of the functionality of the given instruction. Most of these likely generate additional instructions around just the relevant one, or generate different instruction(s) altogether depending on compiler and context in which the snippets are used within a larger codebase.
- ↑ 2.00 2.01 2.02 2.03 2.04 2.05 2.06 2.07 2.08 2.09 2.10 2.11 2.12 2.13 2.14 2.15 2.16 2.17 2.18 2.19 2.20 2.21 2.22 2.23 2.24 2.25 2.26 2.27 2.28 2.29 2.30 2.31 2.32 2.33 2.34 2.35 2.36 2.37 2.38 2.39 This instruction has a variant with the
.
suffix, which indicates the instruction will update the CR special register based on the result of its operation, otherwise it behaves identically to the normal variant described on the table. - ↑ 3.00 3.01 3.02 3.03 3.04 3.05 3.06 3.07 3.08 3.09 3.10 3.11 3.12 3.13 This instruction has a variant with the
o
suffix, which indicates the instruction will enable the overflow bit [OV] in the XER special register, otherwise it behaves identically to the normal variant described on the table aside from different behavior caused by the overflow bit. This suffix can be combined with the.
suffix if the base instruction supports it. (Resulting in ano.
suffix) - ↑ These instructions are exclusive to the Broadway (Wii) and Espresso (Wii U) processors, they are not part of standard PowerPC Assembly and never existed outside the Wii and Wii U.
- ↑ 5.0 5.1 This instruction is too complex to be explained in brief terms on a cheatsheet. Most instructions of this kind are extremely rare and you are unlikely to ever encounter them, and even if you do, even less likely that you will need to know its behavior to understand the surrounding code. If you really need to learn this instruction refer to the processor manuals.