Custom Code/PowerPC Assembly Cheatsheet: Difference between revisions

From Zenith
Jump to navigation Jump to search
Content added Content deleted
(finish most comparison branches, start cmp*)
(add paired shangles instructions)
 
(19 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{DISPLAYTITLE:PowerPC ASM Cheatsheet}}
{{DISPLAYTITLE:PowerPC Assembly Cheatsheet}}
Instructions, registers and general info cheatsheet for PowerPC 32-bit Big Endian Assembly architecture used by the Wii U.
Instructions, registers and general info cheatsheet for PowerPC 32-bit Big Endian Assembly architecture used by the Wii U.


== How to read this cheatsheet ==
== 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 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)
* 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>'''
* 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.
* <nowiki>#</nowiki> = 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)
* <nowiki>#</nowiki> = 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#)
* r# = register (shorthand for GPR#)
Line 12: Line 16:
* i# = immediate (the subscript numbers next to it is it's size in bits)
* i# = immediate (the subscript numbers next to it is it's size in bits)
* ui# = unsigned immediate (above is signed)
* ui# = unsigned immediate (above is signed)
* Instruction parameters wrapped in [ ] are optional and can be omitted.
* <nowiki>*</nowiki> = unsure of exact functionality
* <nowiki>*</nowiki> = 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.
{| class="mw-collapsible mw-collapsed" style="min-width: 250px"
{| class="mw-collapsible mw-collapsed" style="min-width: 250px"
|+'''Pseudocode Typedefs'''
|+'''Pseudocode Typedefs'''
Line 143: Line 149:
|Volatile
|Volatile
|32
|32
|Stores the counter of loop iterations for most instructions that perform loops
|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
|-
|-
|XER
|MSR
|fiXed point Exception Register
|Machine State Register
|Special
|Volatile
|32
|32
|Stores bits with information about the CPU and its current state
|???
|-
|-
|SRR0
|FPSCR
|machine status Save/Restore Register 0
|Floating Point Status and Control Register
|Interrupt-only
|Volatile
|32
|32
|When an exception occurs, holds the address where instruction processing should resume when the exception handler returns control to the interrupted process
|???
|-
|-
|SRR1
|<small>''...''</small>
|machine status Save/Restore Register 1
|<small>''There are way more but less common SPRs which won't be listed here''</small>
|Interrupt-only
|<small>''-''</small>
|32
|<small>''-''</small>
|Stores machine status (select MSR bits and possibly other status bits as well) on exceptions, in order to restore those values when an <code>rfi</code> instruction is executed
|<small>''For a full but undescriptive list of all SPRs, visit [https://wiiubrew.org/wiki/Hardware/Espresso wiiubrew.org/Hardware/Espresso]''</small>
|-
|-
|[[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#CR|CR]]
|CR
|Condition Register
|Condition Register
|Volatile / Saved
|Mixed (See below)
|32
|32
|Divided in 8 bitfields of 4 bits each to hold different kinds of conditions. See below for details.
|Divided in 8 bitfields of 4 bits each to hold different kinds of conditions
|-
|-
|[[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#XER|XER]]
! colspan="5" |SPR: Condition Register (CR)
|fiXed point Exception Register
|-
|cr0
|Condition Register Bitfield 0
|Volatile
|Volatile
|4
|32
|Indicates overflows and carry conditions for integer operations and the number of bytes to be transferred by the load/store string indexed instructions
|Stores a condition
|-
|-
|[[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#FPSCR|FPSCR]]
|cr1
|Floating Point Status and Control Register
|Condition Register Bitfield 1
|Volatile
|Volatile
|4
|32
|Contains all floating point exception signal bits, exception summary bits, exception enable bits, and rounding control bits needed for compliance with the [https://en.wikipedia.org/wiki/IEEE_754 IEEE754] floating point arithmetic standard
|Stores a condition ("floating point invalid exception")
|-
|-
|[[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#TB|TB]]
|cr2 - cr4
|Time Base
|Condition Register Bitfield 2 - 4
|Special
|Saved
|64
|4 x3
|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 [[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#TB|TBU]] and [[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#TB|TBL]].
|Stores a condition
|-
|-
|<small>''...''</small>
|cr5 - cr7
|<small>''There are way more but less common SPRs which won't be listed here''</small>
|Condition Register Bitfield 5 - 7
|<small>''-''</small>
|Volatile
|<small>''-''</small>
|4 x3
|<small>''For a full but undescriptive list of all SPRs, visit [https://wiiubrew.org/wiki/Hardware/Espresso wiiubrew.org/Hardware/Espresso]''</small>
|Stores a condition
|}
|}


Line 205: Line 209:
!Additional Info
!Additional Info
|-
|-
! colspan="5" |Integer Arithmetic Instructions
|<code>add</code>
|-
|<code>add</code><ref name=":0">This instruction has a variant with the <code>.</code> suffix, which indicates the instruction will update the [[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#CR|CR]] special register based on the result of its operation, otherwise it behaves identically to the normal variant described on the table.</ref><ref name=":1">This instruction has a variant with the <code>o</code> suffix, which indicates the instruction will enable the overflow bit [OV] in the [[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#XER|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 <code>.</code> suffix if the base instruction supports it. (Resulting in an <code>o.</code> suffix)</ref>
|ADD operation
|ADD operation
|<code>rA, rB, rC</code>
|<code>rA = rB + rC</code>
|Adds the values of rB and rC together and stores the result in rA
|-
|<code>addc</code><ref name=":0" /><ref name=":1" />
|ADD Carrying
|<code>rA, rB, rC</code>
|<code>rA, rB, rC</code>
|<code>rA = rB + rC</code>
|<code>rA = rB + rC</code>
Line 214: Line 226:
|ADD Immediate
|ADD Immediate
|<code>rA, rB, iX₁₆</code>
|<code>rA, rB, iX₁₆</code>
|<code>rA = rB + iX</code>
|Adds the values of rB and iX together and stores the result in rA
|-
|<code>addic</code><ref name=":0" />
|ADD Immediate Carrying
|<code>rA, rB, iX₅</code>
|<code>rA = rB + iX</code>
|<code>rA = rB + iX</code>
|Adds the values of rB and iX together and stores the result in rA
|Adds the values of rB and iX together and stores the result in rA
Line 223: Line 241:
|Adds the values of rB and (iX << 16) together and stores the result in rA
|Adds the values of rB and (iX << 16) together and stores the result in rA
|-
|-
|<code>and</code>
|<code>adde</code><ref name=":0" /><ref name=":1" />
|ADD Extended
| AND Operation
|<code>rA, rB, rC</code>
|<code>rA, rB, rC</code>
|<code>rA = rB & rC</code>
|<code>rA = rB + rC + XER[CA]</code>
|Performs an AND operation on rB and rC then stores the result in rA
|Adds the values of rB, rC and [[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#XER|XER]][CA] together and stores the result in rA
|-
|-
|<code>andc</code>
|<code>addme</code><ref name=":0" /><ref name=":1" />
|ADD to Minus one Extended
|AND Complement
|<code>rA, rB</code>
|<code>rA = rB + XER[CA] + 0xFFFFFFFF</code>
|Adds the values of rB, [[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#XER|XER]][CA] and 0xFFFFFFFF together and stores the result in rA
|-
|<code>addze</code><ref name=":0" /><ref name=":1" />
|ADD to Zero Extended
|<code>rA, rB</code>
|<code>rA = rB + XER[CA]</code>
|Adds the values of rB and [[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#XER|XER]][CA] together and stores the result in rA
|-
|<code>subf</code><ref name=":0" /><ref name=":1" />
|SUBtract From
|<code>rA, rB, rC</code>
|<code>rA, rB, rC</code>
|<code>rA = rB & ~rC</code>
|<code>rA = rC - rB</code>
|Performs an AND operation on rB and negated rC then stores the result in rA
|Subtracts the value of rB from rC and stores the result in rA.
|-
|<code>subfc</code><ref name=":0" /><ref name=":1" />
|SUBtract From, Carrying
|<code>rA, rB, rC</code>
|<code>rA = rC - rB</code>
|Subtracts the value of rB from rC and stores the result in rA.
|-
|<code>subfic</code>
|SUBtract From Immediate Carrying
|<code>rA, rB, iX₅</code>
|<code>rA = iX - rB</code>
|Subtracts the value of iX from rC and stores the result in rA. (CRO is modified)
|-
|<code>subfe</code><ref name=":0" /><ref name=":1" />
|SUBtract From, Extended
|<code>rA, rB, rC</code>
|<code>rA = (rC - rB) + XER[CA]</code>
|Subtracts the value of rB from rC and adds the value of [[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#XER|XER]][CA] to the result, then stores the final result in rA
|-
|<code>subfme</code><ref name=":0" /><ref name=":1" />
|SUBtract From Minus one Extended
|<code>rA, rB</code>
|<code>rA = (XER[CA] - rB) + 0xFFFFFFFF</code>
|Subtracts the value of rB from [[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#XER|XER]][CA], adds 0xFFFFFFFF to the result, then stores the final result in rA
|-
|<code>subfze</code><ref name=":0" /><ref name=":1" />
|SUBtract From Zero Extended
|<code>rA, rB</code>
|<code>rA = XER[CA] - rB</code>
|Subtracts the value of rB from [[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#XER|XER]][CA] and stores the result in rA
|-
|<code>neg</code><ref name=":0" /><ref name=":1" />
|NEGate
|<code>rA, rB</code>
|<code>rA = 1 - rB</code>
|Subtracts the value of rB from 1 and stores the result in rA
|-
|<code>mulli</code>
|MULtiply Low Immediate
|<code>rA, rB, iX₁₆</code>
|<code>rA = (rB * iX) & 0xFFFFFFFF</code>
|Multiplies the value of rB by iX and stores the lower 32 bits of the result in rA
|-
|<code>mullw</code><ref name=":0" /><ref name=":1" />
|MULtiply Low Word
|<code>rA, rB, rC</code>
|<code>rA = (rB * rC) & 0xFFFFFFFF</code>
|Multiplies the value of rB by the value of rC and stores the lower 32 bits of the result in rA
|-
|<code>mulhw</code><ref name=":0" />
|MULtiply High Word
|<code>rA, rB, rC</code>
|<code>rA = (rB * rC) >> 32</code>
|Multiplies the value of rB by the value of rC and stores the upper 32 bits of the result in rA
|-
|<code>mulhwu</code><ref name=":0" />
|MULtiply High Word Unsigned
|<code>rA, rB, rC</code>
|<code>rA = ((uint)rB * (uint)rC) >> 32</code>
|Multiplies the unsigned value of rB by the unsigned value of rC and stores the upper 32 bits of the result in rA
|-
|<code>divw</code><ref name=":0" /><ref name=":1" />
|DIVide Word
|<code>rA, rB, rC</code>
|<code>rA = rB / rC</code>
|Divides the value of rB by the value of rC and stores the result in rA. The remainder is lost.
|-
|<code>divwu</code><ref name=":0" /><ref name=":1" />
|DIVide Word Unsigned
|<code>rA, rB, rC</code>
|<code>rA = (uint)rB / (uint)rC</code>
|Divides the unsigned value of rB by the unsigned value of rC and stores the result in rA. The remainder is lost.
|-
! colspan="5" |Integer Comparison Instructions
|-
| colspan="5" |
* If the optional parameter <code>cr#</code> is omitted, <code>cr0</code> is used.
* The constant parameter <code>0</code> can only be set to 1 in 64-bit CPUs, so in the case of the Wii U it will always be zero and does effectively nothing.
|-
|<code>cmp</code>
|CoMPare
|<code>[cr#,] 0, rA, rB</code>
|''N/A''
|The value of rA is compared to the value of rB, the results of the comparison are stored in cr#
|-
|<code>cmpi</code>
|CoMPare Immediate
|<code>[cr#,] 0, rA, iX</code>
|''N/A''
|The value of rA is compared to iX, the results of the comparison are stored in cr#
|-
|<code>cmpl</code>
|CoMPare Logical
|<code>[cr#,] 0, rA, rB</code>
|''N/A''
|The unsigned value of rA is compared to the unsigned value of rB, the results of the comparison are stored in cr#
|-
|<code>cmpli</code>
|CoMPare Logical Immediate
|<code>[cr#,] 0, rA, uiX</code>
|''N/A''
|The unsigned value of rA is compared to uiX, the results of the comparison are stored in cr#
|-
|<code>cmpw</code>
|CoMPare Word
|<code>rA, rB</code>
|''N/A''
|
|-
|<code>cmpwi</code>
|CoMPare Word Immediate
|<code>rA, iX₁₆</code>
|''N/A''
|
|-
|<code>cmplwi</code>
|CoMPare Logical Word Immediate
|
|''N/A''
|
|-
! colspan="5" |Integer Logical Instructions
|-
|-
|<code>andi.</code>
|<code>andi.</code>
Line 246: Line 398:
|<code>rA = rB & (uiX << 16)</code>
|<code>rA = rB & (uiX << 16)</code>
|Performs an AND operation on rB and (uiX << 16) then stores the result in rA
|Performs an AND operation on rB and (uiX << 16) then stores the result in rA
|-
|<code>ori</code>
|OR Immediate
|<code>rA, rB, iX₁₆</code>
|<code><nowiki>rA = rB | iX</nowiki></code>
|<nowiki>Stores in rA the result of (rB | iX)</nowiki>
|-
|<code>oris</code>
|OR Immediate Shifted
|<code>rA, rB, iX₁₆</code>
|<code><nowiki>rA = rB | (iX << 16)</nowiki></code>
|<nowiki>Stores in rA the result of (rB | (iX << 16))</nowiki>
|-
|<code>xori</code>
|XOR Immediate
|<code>rA, rB, iX₁₆</code>
|<code>rA = rB ^ iX</code>
|Performs an XOR operation on rB and iX then stores the result in rA
|-
|<code>xoris</code>
|XOR Immediate Shifted
|<code>rA, rB, iX₁₆</code>
|<code>rA = rB ^ (iX << 16)</code>
|Performs an XOR operation on rB and (iX << 16) then stores the result in rA
|-
|<code>and</code><ref name=":0" />
| AND Operation
|<code>rA, rB, rC</code>
|<code>rA = rB & rC</code>
|Performs an AND operation on rB and rC then stores the result in rA
|-
|<code>or</code><ref name=":0" />
|OR operation
|<code>rA, rB, rC</code>
|<code><nowiki>rA = rB | rC</nowiki></code>
|<nowiki>Stores in rA the result of (rB | rC)</nowiki>
|-
|<code>xor</code><ref name=":0" />
|XOR operation
|<code>rA, rB, rC</code>
|<code>rA = rB ^ rC</code>
|Performs an XOR operation on rB and rC then stores the result in rA
|-
|<code>nand</code><ref name=":0" />
|NAND operation
|<code>rA, rB, rC</code>
|<code>rA = ~(rB & rC)</code>
|Stores in rA the negated result of (rB & rC)
|-
|<code>nor</code><ref name=":0" />
|NOR operation
|<code>rA, rB, rC</code>
|<code><nowiki>rA = ~(rB | rC)</nowiki></code>
|<nowiki>Stores in rA the negated result of (rB | rC)</nowiki>
|-
|<code>eqv</code> *<ref name=":0" />
|EQuiValent
|<code>rA, rB, rC</code>
|<code>rA = rB == rC</code>
|Compares if the values of rB and rC are equal and stores the result in rA (?)
|-
|<code>andc</code><ref name=":0" />
|AND Complement
|<code>rA, rB, rC</code>
|<code>rA = rB & ~rC</code>
|Performs an AND operation on rB and negated rC then stores the result in rA
|-
|<code>orc</code><ref name=":0" />
|OR Complement
|<code>rA, rB, rC</code>
|<code><nowiki>rA = rB | ~rC</nowiki></code>
|<nowiki>Stores in rA the result of (rB | ~rC)</nowiki>
|-
|<code>extsb</code><ref name=":0" />
|EXTend Sign Byte
|<code>rA, rB</code>
|<code>rA = (int8_t)rB</code>
|Fills the upper 24 bits of rB's value with the sign bit of the stored 8 bit value
|-
|<code>extsh</code><ref name=":0" />
|EXTend Sign Halfword
|<code>rA, rB</code>
|<code>rA = (int16_t)rB</code>
|Fills the upper 16 bits of rB's value with the sign bit of the stored 16 bit value
|-
|<code>cntlzw</code><ref name=":0" />
|CouNT Leading Zeros Word
|<code>rA, rB</code>
|''N/A''
|Stores into rA the number of consecutive leading zero bits in the value of rB
|-
! colspan="5" |Integer Rotate Instructions
|-
|<code>rlwinm</code><ref name=":0" />
|Rotate Left Word Immediate, aNd with Mask
|<code>rA,{{nbsp}}rB,{{nbsp}}iX₅,{{nbsp}}iY₅,{{nbsp}}iZ₅</code>
|<syntaxhighlight lang="c++">
uint mask = ((uint)-1) << (31 - iZ + iY) >> iY;
rA = (rB << iX) | (rB >> (32 - iX)) & mask;
</syntaxhighlight>
|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
|-
|<code>rlwnm</code><ref name=":0" />
|Rotate Left Word, aNd with Mask
|
|
|
|-
|<code>rlwimi</code><ref name=":0" />
|Rotate Left Word Immediate, Mask Insert
|
|
|
|-
! colspan="5" |Integer Shift Instructions
|-
|<code>slw</code><ref name=":0" />
|Shift Left Word
|<code>rA, rB, rC</code>
|<code>rA = rB << rC</code>
|Shifts the value in rB by the value in rC to the left and stores the result in rA
|-
|<code>srw</code><ref name=":0" />
|Shift Right Word
|<code>rA, rB, rC</code>
|<code>rA = (unsigned)rB >> rC</code>
|Shifts the value in rB by the value in rC to the right and stores the result in rA
|-
|<code>srawi</code><ref name=":0" />
|Shift Right Algebraic Word Immediate
|<code>rA, rB, iX₅</code>
|<code>rA = (signed)rB >> iX</code>
|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
|-
|<code>sraw</code><ref name=":0" />
|Shift Right Algebraic Word
|<code>rA, rB, rC</code>
|<code>rA = (signed)rB >> rC</code>
|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
|-
|<code>slwi</code>
|Shift Left Word Immediate
|<code>rA, rB, iX₅</code>
|<code>rA = rB << iX</code>
|Shifts the value in rB by iX to the left and stores the result in rA
|-
|<code>srwi</code>
|Shift Right Word Immediate
|<code>rA, rB, iX₅</code>
|<code>rA = (unsigned)rB >> iX</code>
|Shifts the value in rB by iX to the right and stores the result in rA
|-
! colspan="5" |Floating Point Arithmetic Instructions
|-
! colspan="5" |Floating Point Multiply-Add Instructions
|-
! colspan="5" |Floating Point Rounding & Conversion Instructions
|-
! colspan="5" |Floating Point Comparison Instructions
|-
! colspan="5" |[[Custom Code/PowerPC ASM Cheatsheet/Special Purpose Registers#FPSCR|Floating Point Status and Control Register]] Instructions
|-
! colspan="5" |Floating Point Move Instructions
|-
|<code>fmr</code><ref name=":0" />
|Float Move Register
|<code>fA, fB</code>
|<code>fA = fB</code>
|Copies the value of fB into fA (Despite the instruction name, fB is preserved)
|-
|<code>fneg</code><ref name=":0" />
|Float Negate
|<code>fA, fB</code>
|<code>fA = -fB</code>
|Negates the value of fB and stores the result in fA
|-
|<code>fabs</code><ref name=":0" />
|Float Absolute
|<code>fA, fB</code>
|<code>fA = abs(fB)</code>
|The absolute value of fB is stored into rA
|-
|<code>fnabs</code><ref name=":0" />
|Float Negative Absolute
|<code>fA, fB</code>
|<code>fA = -abs(fB)</code>
|The negative absolute value of fB is stored into rA
|-
! colspan="5" |Floating Point Load Instructions
|-
|<code>lfs</code>
|Load Float Single
|<code>fA, iX₁₆(rA)</code>
|<code>fA = (float)(*(rA + iX))</code>
|Loads the value at the address (rA + iX) casted to float into fA.
|-
|<code>lfsx</code>
|Load Float Single indeXed
|
|
|
|-
|<code>lfsu</code>
|Load Float Single Update
|
|
|
|-
|<code>lfsux</code>
|Load Float Single Update indeXed
|
|
|
|-
|<code>lfd</code>
|Load Float Double
|<code>fA, iX₁₆(rA)</code>
|<code>fA = (double)(*(rA + iX))</code>
|Loads the 64 bit value at the address (rA + iX) casted to double into fA.
|-
|<code>lfdx</code>
|Load Float Double indeXed
|
|
|
|-
|<code>lfdu</code>
|Load Float Double Update
|
|
|
|-
|<code>lfdux</code>
|Load Float Double Update indeXed
|
|
|
|-
! colspan="5" |Floating Point Store Instructions
|-
|<code>stfs</code>
|STore Float Single
|<code>fA, iX₁₆(rA)</code>
|<code>*(rA + iX) = (float)fA</code>
|Stores the value of fA casted to float at the memory address (rA + iX)
|-
|<code>stfsx</code>
|STore Float Single indeXed
|
|
|
|-
|<code>stfsu</code>
|STore Float Single Update
|
|
|
|-
|<code>stfsux</code>
|STore Float Single Update indeXed
|
|
|
|-
|<code>stfd</code>
|STore Float Double
|<code>fA, iX₁₆(rA)</code>
|<code>*(rA + iX) = fA</code>
|Stores the 64 bit value of fA at the memory address (rA + iX)
|-
|<code>stfdx</code>
|STore Float Double indeXed
|
|
|
|-
|<code>stfdu</code>
|STore Float Double Update
|
|
|
|-
|<code>stfdux</code>
|STore Float Double Update indeXed
|
|
|
|-
|<code>stfiwx</code>
|STore Float as Integer Word indeXed
|
|
|
|-
! colspan="5" |Paired Singles Instructions (WIP)<ref>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.</ref>
|-
|<code>psq_l</code>
|<small>Paired Single</small> Quantized Load
|
|
|
|-
|<code>psq_lx</code>
|<small>Paired Single</small> Quantized Load indeXed
|
|
|
|-
|<code>psq_lu</code>
|<small>Paired Single</small> Quantized Load Update
|
|
|
|-
|<code>psq_lux</code>
|<small>Paired Single</small> Quantized Load Update indeXed
|
|
|
|-
|<code>psq_st</code>
|<small>Paired Single</small> Quantized Store
|
|
|
|-
|<code>psq_stx</code>
|<small>Paired Single</small> Quantized Store indeXed
|
|
|
|-
|<code>psq_stu</code>
|<small>Paired Single</small> Quantized Store Update
|
|
|
|-
|<code>psq_stux</code>
|<small>Paired Single</small> Quantized Store Update indeXed
|
|
|
|-
|<code>ps_abs</code>
|<small>Paired Single</small> ABSolute
|
|
|
|-
|<code>ps_add</code>
|<small>Paired Single</small> ADD
|
|
|
|-
|<code>ps_cmpo0</code>
|<small>Paired Single</small> CoMPare Ordered high(0)
|
|
|
|-
|<code>ps_cmpo1</code>
|<small>Paired Single</small> CoMPare Ordered low(1)
|
|
|
|-
|<code>ps_cmpu0</code>
|<small>Paired Single</small> CoMPare Unordered high(0)
|
|
|
|-
|<code>ps_cmpu1</code>
|<small>Paired Single</small> CoMPare Unordered low(1)
|
|
|
|-
|<code>ps_div</code>
|<small>Paired Single</small> DIVide
|
|
|
|-
|<code>ps_madd</code>
|<small>Paired Single</small> Multiply & ADD
|
|
|
|-
|<code>ps_madds0</code>
|<small>Paired Single</small> Multiply & ADD Scalar high(0)
|
|
|
|-
|<code>ps_madds1</code>
|<small>Paired Single</small> Multiply & ADD Scalar low(1)
|
|
|
|-
|<code>ps_merge00</code>
|<small>Paired Single</small> MERGE high(00)
|
|
|
|-
|<code>ps_merge01</code>
|<small>Paired Single</small> MERGE direct(01)
|
|
|
|-
|<code>ps_merge10</code>
|<small>Paired Single</small> MERGE swapped(10)
|
|
|
|-
|<code>ps_merge11</code>
|<small>Paired Single</small> MERGE low(11)
|
|
|
|-
|<code>ps_mr</code>
|<small>Paired Single</small> Move Register
|
|
|
|-
|<code>ps_msub</code>
|<small>Paired Single</small> Multiply & SUBtract
|
|
|
|-
|<code>ps_mul</code>
|<small>Paired Single</small> MULtiply
|
|
|
|-
|<code>ps_muls0</code>
|<small>Paired Single</small> MULtiply Scalar high(0)
|
|
|
|-
|<code>ps_muls1</code>
|<small>Paired Single</small> MULtiply Scalar low(1)
|
|
|
|-
|<code>ps_nabs</code>
|<small>Paired Single</small> Negative ABSolute
|
|
|
|-
|<code>ps_neg</code>
|<small>Paired Single</small> NEGate
|
|
|
|-
|<code>ps_nmadd</code>
|<small>Paired Single</small> Negative Multiply & ADD
|
|
|
|-
|<code>ps_nmsub</code>
|<small>Paired Single</small> Negative Multiply & SUBtract
|
|
|
|-
|<code>ps_res</code>
|<small>Paired Single</small> Reciprocal EStimate
|
|
|
|-
|<code>ps_rsqrte</code>
|<small>Paired Single</small> Reciprocal SQuareRooT Estimate
|
|
|
|-
|<code>ps_sel</code>
|<small>Paired Single</small> SELect
|
|
|
|-
|<code>ps_sub</code>
|<small>Paired Single</small> SUBtract
|
|
|
|-
|<code>ps_sum0</code>
|<small>Paired Single</small> vector SUM high(0)
|
|
|
|-
|<code>ps_sum1</code>
|<small>Paired Single</small> vector SUM low(1)
|
|
|
|-
! colspan="5" |Integer Load Instructions
|-
|<code>lbz</code>
|Load Byte Zero-fill
|<code>rA, iX₁₆(rB)</code>
|<code>rA = (ubyte)(*(rB + iX))</code>
|Loads the 8 bit value at the address (rB + iX) into rA
|-
|<code>lbzx</code>
|Load Byte Zero-fill indeXed
|
|
|
|-
|<code>lbzu</code>
|Load Byte Zero-fill Update
|
|
|
|-
|<code>lbzux</code>
|Load Byte Zero-fill Update indeXed
|
|
|
|-
|<code>lhz</code>
|Load Halfword Zero-fill
|<code>rA, iX₁₆(rB)</code>
|<code>rA = (ushort)(*(rB + iX))</code>
|Loads the 16 bit value at the address (rB + iX) into rA
|-
|<code>lhzx</code>
|Load Halfword Zero-fill indeXed
|
|
|
|-
|<code>lhzu</code>
|Load Halfword Zero-fill Update
|
|
|
|-
|<code>lhzux</code>
|Load Halfword Zero-fill Update indeXed
|
|
|
|-
|<code>lha</code>
|Load Halfword Algebraic
|<code>rA, iX₁₆(rB)</code>
|
|
|-
|<code>lhax</code>
|Load Halfword Algebraic indeXed
|
|
|
|-
|<code>lhau</code>
|Load Halfword Algebraic Update
|
|
|
|-
|<code>lhaux</code>
|Load Halfword Algebraic Update indeXed
|
|
|
|-
|<code>lwz</code>
|Load Word Zero-fill
|<code>rA, iX₁₆(rB)</code>
|<code>rA = *(rB + iX)</code>
|Loads the value at the address (rB + iX) into rA
|-
|<code>lwzx</code>
|Load Word Zero-fill indeXed
|<code>rA, rB, rC</code>
|<code>rA = *(rB + rC)</code>
|Loads the value at the address (rB + rC) into rA
|-
|<code>lwzu</code>
|Load Word Zero-fill Update
|<code>rA, iX₁₆(rB)</code>
|<syntaxhighlight lang="c++">
rA = *(rB + iX);
rB = rB + iX;
</syntaxhighlight>
|Loads the value at the address (rB + iX) into rA<br />Then loads rB with the address (rB + iX)
|-
|<code>lwzux</code>
|Load Word Zero-fill Update indeXed
|
|
|
|-
|<code>lmw</code> *
|Load Multiple Words
|<code>rA, iX₁₆(rB)</code>
|<syntaxhighlight lang="c++">int EA = rB + iX;
int N = rA;
do {
GPR[N] = *(EA);
EA = EA + 4;
N = N + 1;
} while (N <= 31);</syntaxhighlight>
|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.


<u>Example</u>: Assume '''r0 = 29''' and '''r1 = 0x20000000'''<br /><code>lmw r0, 0x20(r1)</code><br />This will load the following registers like so:<br /><code>r29 = *(0x20000020)</code><br /><code>r30 = *(0x20000024)</code><br /><code>r31 = *(0x20000028)</code>
|-
! colspan="5" |Integer Store Instructions
|-
|<code>stb</code>
|STore Byte
|<code>rA, iX₁₆(rB)</code>
|<code>*(rB + iX) = (ubyte)rA</code>
|Stores the 8 bit value of rA at the memory address (rB + iX)
|-
|<code>stbx</code>
|STore Byte indeXed
|
|
|
|-
|<code>stbu</code>
|STore Byte Update
|
|
|
|-
|<code>stbux</code>
|STore Byte Update indeXed
|
|
|
|-
|<code>sth</code>
|STore Halfword
|<code>rA, iX₁₆(rB)</code>
|<code>*(rB + iX) = (ushort)rA</code>
|Stores the 16 bit value of rA at the memory address (rB + iX)
|-
|<code>sthx</code>
|STore Halfword indeXed
|
|
|
|-
|<code>sthu</code>
|STore Halfword Update
|
|
|
|-
|<code>sthux</code>
|STore Halfword Update indeXed
|
|
|
|-
|<code>stw</code>
|STore Word
|<code>rA, iX₁₆(rB)</code>
|<code>*(rB + iX) = rA</code>
|Stores the value of rA at the memory address (rB + iX)
|-
|<code>stwx</code>
|STore Word indeXed
|<code>rA, rB, rC</code>
|<code>*(rB + rC) = rA</code>
|Stores the value of rA at the memory address (rB + rC)
|-
|<code>stwu</code>
|STore Word And Update
|<code>rA, iX₁₆(rB)</code>
|<code>*(rB + iX) = rA</code>
<code>rB = rB + iX</code>
|Stores the value of rA at the memory address (rB + iX)
Stores the computed address (rB + iX) into rB
|-
|<code>stwux</code>
|STore Word And Update indeXed
|<code>rA, rB, rC</code>
|
|
|-
|<code>stmw</code> *
|STore Multiple Words
|
|
|
|-
! colspan="5" |Little Endian Integer Load & Store Instructions
|-
! colspan="5" |Integer Load and Store Strings Instructions
|-
|
|
|
|
|
|-
|
|
|
|
|
|-
|
|
|
|
|
|-
! colspan="5" |Branch Instructions
|-
|-
|<code>b</code>
|<code>b</code>
Line 252: Line 1,154:
|<code>goto LABEL</code>
|<code>goto LABEL</code>
|Jumps from the current address to IAR + iX, either up or down
|Jumps from the current address to IAR + iX, either up or down
|-
|<code>ba</code>
|Branch Absolute
|<code>iX₂₄</code>
|<code>goto LABEL</code>
|Jumps from the current address to the address iX, either up or down
|-
|-
|<code>bl</code>
|<code>bl</code>
|Branch and Link
|Branch & Link
|<code>iX₂₄</code>
|<code>iX₂₄</code>
|<code>((void (*)())IAR + iX)()</code>
|<code>((void (*)())IAR + iX)()</code>
|Jumps from the current address to IAR + iX, either up or down
|Jumps from the current address to IAR + iX, either up or down
Also stores the address of the instruction directly below it in LR
Also stores the address of the instruction directly below itself in LR


This is the most common instruction to use for calling a function
''This is the most common instruction used for calling a function''
|-
|<code>bla</code>
|Branch & Link Absolute
|<code>iX₂₄</code>
|<code>((void (*)())IAR + iX)()</code>
|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
|-
|<code>bc</code>
|Branch Conditional
|<code>BO, BI, iX</code>
|
|
|-
|<code>bca</code>
|Branch Conditional Absolute
|<code>BO, BI, iX</code>
|
|
|-
|<code>bcl</code>
|Branch Conditional & Link
|<code>BO, BI, iX</code>
|
|
|-
|<code>bcla</code>
|Branch Conditional & Link Absolute
|<code>BO, BI, iX</code>
|
|
|-
|<code>bclr</code>
|Branch Conditional to Link Register
|<code>BO, BI, BH</code>
|
|
|-
|<code>bclrl</code>
|Branch Conditional to Link Register & Link
|<code>BO, BI, BH</code>
|
|
|-
|<code>bcctr</code>
|Branch Conditional to CounT Register
|<code>BO, BI, BH</code>
|
|
|-
|<code>bcctrl</code>
|Branch Conditional to CounT Register & Link
|<code>BO, BI, BH</code>
|
|
|-
|
|
|
|
|
|-
|-
|<code>blr</code>
|<code>blr</code>
Line 383: Line 1,352:
|
|
|-
|-
! colspan="5" |Condition Register Logical Instructions
|<code>cmp</code>
|CoMPare
|<code>cr#, 0, rA, rB</code>
|
|
|-
|-
! colspan="5" |Move to/from Special Purpose Registers Instructions
|<code>cmpw</code>
|CoMPare Word
|<code>rA, rB</code>
|
|
|-
|<code>cmpwi</code>
|CoMPare Word Immediate
|<code>rA, iX₁₆</code>
|
|
|-
|<code>cmplwi</code>
|CoMPare Logical Word Immediate
|
|
|
|-
|<code>cntlzw</code>
| CouNT Leading Zeros Word
|
|
|
|-
|<code>divw</code>
|DIVide Word
|<code>rA, rB, rC</code>
|<code>rA = rB / rC</code>
|Divides the value of rB by rC and stores the result in rA. The remainder is lost.
|-
|<code>eieio</code>
|Enforce In-order Execution of I/O
|???
|???
|???
|-
|<code>eqv</code>
| EQuiValent
|<code>rA, rB, rC</code>
|<code>rA = rB == rC</code>
|Compares if the values of rB and rC are equal and stores the result in rA (?)
|-
|<code>extsb</code>
|EXTend Sign Byte
|<code>rA, rB</code>
|<code>rA = (int8_t)rB</code>
|Fills the upper 24 bits of rB's value with the sign bit of the stored 8 bit value
|-
|<code>extsh</code>
|EXTend Sign Halfword
|<code>rA, rB</code>
|<code>rA = (int16_t)rB</code>
|Fills the upper 16 bits of rB's value with the sign bit of the stored 16 bit value
|-
|<code>fmr</code>
|Float Move Register
|<code>fA, fB</code>
|<code>fA = fB</code>
|Copies the value of fB into fA (Despite the instruction name, fB is preserved)
|-
|<code>isync</code>
|Instruction SYNChronize
|''N/A''
|''<small>Assembly-only instruction</small>''
|Delay all following instructions until all previous instructions required for context.
|-
|<code>lfs</code>
|Load Float Single
|<code>fA, iX₁₆(rA)</code>
|<code>fA = (float)(*(rA + iX))</code>
|Loads the value at the address (rA + iX) casted to float into fA.
|-
|<code>lfd</code>
|Load Float Double
|<code>fA, iX₁₆(rA)</code>
|<code>fA = (double)(*(rA + iX))</code>
|Loads the 64 bit value at the address (rA + iX) casted to double into fA.
|-
|<code>lbz</code>
|Load Byte Zero-fill
|<code>rA, iX₁₆(rB)</code>
|<code>rA = (ubyte)(*(rB + iX))</code>
|Loads the 8 bit value at the address (rB + iX) into rA
|-
|<code>lhz</code>
|Load Halfword Zero-fill
|<code>rA, iX₁₆(rB)</code>
|<code>rA = (ushort)(*(rB + iX))</code>
|Loads the 16 bit value at the address (rB + iX) into rA
|-
|<code>li</code>
|Load Immediate
|<code>rA, iX₁₆</code>
|<code>rA = iX</code>
|Loads iX into rA
|-
|<code>lis</code>
|Load Immediate Shifted
|<code>rA, iX₁₆</code>
| `rA="rA" |<code><nowiki>rA = rA | (iX << 16)</nowiki></code>
|Loads iX into the upper 16 bits of rA
|-
|<code>lwz</code>
|Load Word Zero-fill
|<code>rA, iX₁₆(rB)</code>
|<code>rA = *(rB + iX)</code>
|Loads the value at the address (rB + iX) into rA
|-
|<code>la</code>
|Load Address
|<code>rA, iX₁₆(rB)</code>
|<code>rA = rB + iX</code>
|Adds iX to the address stored in rB and loads the result into rA.
|-
|<code>lwzu</code>
|Load Word Zero Update
|<code>rA, iX₁₆(rB)</code>
|<syntaxhighlight lang="c++">
rA = *(rB + iX);
rB = rB + iX;
</syntaxhighlight>
|Loads the value at the address (rB + iX) into rA<br />Then loads rB with the address (rB + iX)
|-
|<code>lwzx</code>
|Load Word Zero indeXed
|<code>rA, rB, rC</code>
|<code>rA = *(rB + rC)</code>
|Loads the value at the address (rB + rC) into rA
|-
|<code>lmw</code> *
|Load Multiple Words
|<code>rA, iX₁₆(rB)</code>
|<syntaxhighlight lang="c++">int EA = rB + iX;
int N = rA;
do {
GPR[N] = *(EA);
EA = EA + 4;
N = N + 1;
} while (N <= 31);</syntaxhighlight>
|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.


<u>Example</u>: Assume '''r0 = 29''' and '''r1 = 0x20000000'''<br /><code>lmw r0, 0x20(r1)</code><br />This will load the following registers like so:<br /><code>r29 = *(0x20000020)</code><br /><code>r30 = *(0x20000024)</code><br /><code>r31 = *(0x20000028)</code>
|-
|<code>mr</code>
|Move Register
|<code>rA, rB</code>
|<code>rA = rB</code>
|Copies the value of rB into rA (Despite the instruction name, rB is preserved)
|-
|-
|<code>mflr</code>
|<code>mflr</code>
Line 556: Line 1,372:
|<code>rA</code>
|<code>rA</code>
|<code>CTR = rA</code>
|<code>CTR = rA</code>
| Copies the value of rA into the CTR
|Copies the value of rA into the CTR
|-
|<code>mtspr</code>
|Move To Special Purpose Register
|<code>SPR, rA</code>
|<code>SPRs[SPR] = rA</code>
|Copies the value of rA into the special purpose register SPR
|-
|-
|<code>mtfsf</code> *
|<code>mtfsf</code> *
Line 576: Line 1,386:
|Sets bit iX of the FPSCR register to 1
|Sets bit iX of the FPSCR register to 1
|-
|-
|
|<code>mullw</code>
|
|MULtiply Low Word
|
|<code>rA, rB, rC</code>
|
|<code>rA = (int64_t)(rB * rC) & 0xFFFFFFFF</code>
|
|Multiplies the value of rB by rC and stores the low 32 bits of the result in rA
|-
|-
|<code>mullh</code>
|<code>mtspr</code>
|Move To Special Purpose Register
|MULtiply (L) High word
|<code>rA, rB, rC</code>
|<code>SPR, rA</code>
|<code>rA = (int64_t)(rB * rC) >> 32</code>
|<code>SPRs[SPR] = rA</code>
|Multiplies the value of rB by rC and stores the high 32 bits of the result in rA
|Copies the value of rA into the special purpose register SPR
|-
|-
|<code>mulli</code>
|<code>mfspr</code>
|Move From Special Purpose Register
|MULtiply Low Immediate
|<code>rA, rB, iX₁₆</code>
|<code>rA, SPR</code>
|<code>rA = rB * iX</code>
|<code>rA = SPRs[SPR]</code>
|Multiplies the value of rB by iX and stores the result in rA
|Copies the value of special purpose register SPR into rA
|-
|-
|<code>nand</code>
|<code>mfmsr</code>
|Move From Machine State Register
|NAND operation
|<code>rA, rB, rC</code>
|<code>rA</code>
|<code>rA = ~(rB & rC)</code>
|<code>rA = MSR</code>
|Stores in rA the negated result of (rB & rC)
|Copies the value of MSR into rA
|-
|-
|<code>neg</code>
|<code>mftb</code>
|Move From Time Base
|NEGate
|<code>rA, rB</code>
|<code>rA [, TBR]</code>
|''N/A''
|<code>rA = ~rB + 1</code>
|Stores in rA the result of negated rB with 1 added to it's value afterwards
|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
|-
|-
|<code>nop</code>
|<code>mftbu</code>
|Move From Time Base Upper
|No OPeration
|<code>rA</code>
|''N/A''
|''N/A''
|Copies the value of TBU (Time Base Upper) into rA
|<code>;</code>
|Does nothing
|-
|-
! colspan="5" |Trap Instructions
|<code>nor</code>
|NOR operation
|<code>rA, rB, rC</code>
| `rA="~(rB" |<code><nowiki>rA = ~(rB | rC)</nowiki></code>
|<nowiki>Stores in rA the negated result of (rB | rC)</nowiki>
|-
|-
|<code>not</code>
|<code>twi</code>
|Trap Word Immediate
|NOT operation
|<code>rA, rB</code>
|<code>TO, rA, iX</code>
|
|<code>rA = ~rB</code>
|
|Stores in rA the result of negated rB
|-
|<code>tw</code>
|Trap Word
|<code>TO, rA, rB</code>
|
|
|-
! colspan="5" |Memory Synchronization Instructions
|-
|-
|<code>or</code>
|<code>lwarx</code>
|Load Word And Reserve indeXed
|OR operation
|<code>rA, rB, rC</code>
|<code>rA, rB, rC</code>
|
| `rA="rB" |<code><nowiki>rA = rB | rC</nowiki></code>
|
|<nowiki>Stores in rA the result of (rB | rC)</nowiki>
|-
|-
|<code>orc</code>
|<code>stwcx.</code>
|STore Word Conditional indeXed
|OR Complement
|<code>rA, rB, rC</code>
|<code>rA, rB, rC</code>
|
| `rA="rB" |<code><nowiki>rA = rB | ~rC</nowiki></code>
|
|<nowiki>Stores in rA the result of (rB | ~rC)</nowiki>
|-
|-
|<code>ori</code>
|<code>sync</code>
|SYNChronize
| OR Immediate
|<code>rA, rB, iX₁₆</code>
|<code>L</code>
|''<small>Assembly-only instruction</small>''
| `rA="rB" |<code><nowiki>rA = rB | iX</nowiki></code>
|Delays all following instructions until all previous instructions required for context are complete.
|<nowiki>Stores in rA the result of (rB | iX)</nowiki>
|-
|-
|<code>oris</code>
|<code>eieio</code>
|Enforce In-order Execution of I/O
|OR Immediate Shifted
|''N/A''
|<code>rA, rB, iX₁₆</code>
|''<small>Assembly-only instruction</small>''
| `rA="rB" |<code><nowiki>rA = rB | (iX << 16)</nowiki></code>
|''"Provides an ordering function for the effects of loads and stores executed by the processor."''
|<nowiki>Stores in rA the result of (rB | (iX << 16))</nowiki>
|-
|-
|<code>rlwinm</code>
|<code>isync</code>
|Instruction SYNChronize
|Rotate Left Word Immediate aNd Mask
|''N/A''
|<code>rA, rB, iX₅, iY₅, iZ₅</code>
|''<small>Assembly-only instruction</small>''
|<syntaxhighlight lang="c++">
|Delays all following instructions until all previous instructions required for context are complete.
uint mask = ((uint)-1) << (31 - iZ + iY) >> iY;
Additionally discards all prefetched instructions for a context reset.
rA = (rB << iX) | (rB >> (32 - iX)) & mask;
</syntaxhighlight>
| 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
|-
|-
! colspan="5" |Cache Control Instructions
|<code>sc</code>
|System Call
|<code>iX₇</code>
|N/A
| Calls upon the system to perform a service identified by iX
|-
|-
|<code>slw</code>
|<code>dcbz_l</code>
|Data Cache Block Zero and Lock
|Shift Left Word
|<code>rA, rB, rC</code>
|<code>rA, rB</code>
|''<small>Assembly-only instruction</small>''
|<code>rA = rB << rC</code>
|''Too complex.''<ref name=":2">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.</ref>All you might need to know about this instruction is rA+rB form an address input, and it does not modify any registers.
|Shifts the value in rB by the value in rC to the left and stores the result in rA
|-
|-
|<code>slwi</code>
|<code>dcbi</code>
|Data Cache Block Invalidate
|Shift Left Word Immediate
|<code>rA, rB, iX₅</code>
|<code>rA, rB</code>
|''<small>Assembly-only instruction</small>''
|<code>rA = rB << iX</code>
|''Too complex.''<ref name=":2" />
|Shifts the value in rB by iX to the left and stores the result in rA
|-
|-
! colspan="5" |External Control Instructions
|<code>srw</code>
|Shift Right Word
|<code>rA, rB, rC</code>
|<code>rA = (unsigned)rB >> rC</code>
|Shifts the value in rB by the value in rC to the right and stores the result in rA
|-
|-
|<code>srwi</code>
|<code>eciwx</code>
|Shift Right Word Immediate
|External Control In Word indeXed
|<code>rA, rB, iX₅</code>
|<code>rA = (unsigned)rB >> iX</code>
|Shifts the value in rB by iX to the right and stores the result in rA
|-
|<code>sraw</code>
|Shift Right Algebraic Word
|<code>rA, rB, rC</code>
|<code>rA, rB, rC</code>
|
|<code>rA = (signed)rB >> rC</code>
|
|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
|-
|-
|<code>srawi</code>
|<code>ecowx</code>
|Shift Right Algebraic Word Immediate
|External Control Out Word indeXed
|<code>rA, rB, iX₅</code>
|<code>rA = (signed)rB >> iX</code>
|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
|-
|<code>subf</code>
|SUBtract From
|<code>rA, rB, rC</code>
|<code>rA, rB, rC</code>
|
|<code>rA = rC - rB</code>
|
|Subtracts the value of rB from rC and stores the result in rA.
|-
|-
! colspan="5" |Uncategorized instructions (categories WIP)
|<code>subfic</code>
|SUBtract From Immediate Carrying
|<code>rA, rB, iX₅</code>
|<code>rA = iX - rB</code>
|Subtracts the value of iX from rC and stores the result in rA. (CRO is modified)
|-
|-
|<code>stfs</code>
|<code>li</code>
|Load Immediate
|STore Float Single
|<code>fA, iX₁₆(rA)</code>
|<code>rA, iX₁₆</code>
|<code>*(rA + iX) = (float)fA</code>
|<code>rA = iX</code>
|Loads iX into rA
|Stores the value of fA casted to float at the memory address (rA + iX)
|-
|-
|<code>stfd</code>
|<code>lis</code>
|Load Immediate Shifted
|STore Float Double
|<code>fA, iX₁₆(rA)</code>
|<code>rA, iX₁₆</code>
|<code>*(rA + iX) = fA</code>
| `rA="rA" |<code><nowiki>rA = rA | (iX << 16)</nowiki></code>
|Loads iX into the upper 16 bits of rA
|Stores the 64 bit value of fA at the memory address (rA + iX)
|-
|-
|<code>stb</code>
|<code>la</code>
|Load Address
|STore Byte
|<code>rA, iX₁₆(rB)</code>
|<code>rA, iX₁₆(rB)</code>
|<code>*(rB + iX) = (ubyte)rA</code>
|<code>rA = rB + iX</code>
|Stores the 8 bit value of rA at the memory address (rB + iX)
|Adds iX to the address stored in rB and loads the result into rA.
|-
|-
|<code>sth</code>
|<code>mr</code>
|Move Register
|STore Halfword
|<code>rA, iX₁₆(rB)</code>
|<code>rA, rB</code>
|<code>*(rB + iX) = (ushort)rA</code>
|<code>rA = rB</code>
|Stores the 16 bit value of rA at the memory address (rB + iX)
|Copies the value of rB into rA (Despite the instruction name, rB is preserved)
|-
|-
|<code>stw</code>
|<code>not</code>
|NOT operation
|STore Word
|<code>rA, iX₁₆(rB)</code>
|<code>rA, rB</code>
|<code>*(rB + iX) = rA</code>
|<code>rA = ~rB</code>
| Stores the value of rA at the memory address (rB + iX)
|Stores in rA the result of negated rB
|-
|-
! colspan="5" |Misc. Instructions
|<code>stwu</code>
|STore Word And Update
|<code>rA, iX₁₆(rB)</code>
|<code>*(rB + iX) = rA</code>
<code>rB = rB + iX</code>
|Stores the value of rA at the memory address (rB + iX)
Stores the computed address (rB + iX) into rB
|-
|-
|<code>stwx</code>
|<code>nop</code>
|No OPeration
| STore Word indeXed
|''N/A''
|<code>rA, rB, rC</code>
|<code>*(rB + rC) = rA</code>
|<code>;</code>
|Does nothing
|Stores the value of rA at the memory address (rB + rC)
|-
|-
|<code>stmw</code> *
|<code>sc</code>
|System Call
|STore Multiple Words
|<code>[iX₇]</code>
|''N/A''
|Calls upon the system to perform a service identified by iX
If iX is not provided, triggers a system call exception.
|-
|<code>rfi</code>
|Return From Interrupt
|
|
|
|
|
|
|-
|<code>xor</code>
| XOR operation
|<code>rA, rB, rC</code>
|<code>rA = rB ^ rC</code>
|Performs an XOR operation on rB and rC then stores the result in rA
|-
|<code>xori</code>
| XOR Immediate
|<code>rA, rB, iX₁₆</code>
|<code>rA = rB ^ iX</code>
|Performs an XOR operation on rB and iX then stores the result in rA
|-
|<code>xoris</code>
|XOR Immediate Shifted
|<code>rA, rB, iX₁₆</code>
|<code>rA = rB ^ (iX << 16)</code>
|Performs an XOR operation on rB and (iX << 16) then stores the result in rA
|}
|}


Line 797: Line 1,560:
*http://wiibrew.org/wiki/Assembler_Tutorial (also has missing instructions but way more accurate and better worded)
*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)
*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 though)
*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)
*[https://web.archive.org/web/20221024185252/https://wiki.alcf.anl.gov/images/f/fb/PowerPC_-_Assembly_-_IBM_Programming_Environment_2.3.pdf @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://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)

<br>
<hr>
<br>


__NOTOC__
__NOTOC__

Latest revision as of 03:26, 12 August 2023

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 [ ] 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.
Pseudocode Typedefs
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

Registers
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
Instructions
Instruction Name Parameters Pseudocode Equivalent Additional Info
Integer Arithmetic Instructions
add[1][2] ADD operation rA, rB, rC rA = rB + rC Adds the values of rB and rC together and stores the result in rA
addc[1][2] 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[1] 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[1][2] 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[1][2] 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[1][2] 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[1][2] SUBtract From rA, rB, rC rA = rC - rB Subtracts the value of rB from rC and stores the result in rA.
subfc[1][2] 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[1][2] 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[1][2] 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[1][2] 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[1][2] 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[1][2] 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[1] 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[1] 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[1][2] 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[1][2] 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
  • If the optional parameter cr# is omitted, cr0 is used.
  • The constant parameter 0 can only be set to 1 in 64-bit CPUs, so in the case of the Wii U it will always be zero and does effectively nothing.
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[1] AND Operation rA, rB, rC rA = rB & rC Performs an AND operation on rB and rC then stores the result in rA
or[1] OR operation rA, rB, rC rA = rB | rC Stores in rA the result of (rB | rC)
xor[1] XOR operation rA, rB, rC rA = rB ^ rC Performs an XOR operation on rB and rC then stores the result in rA
nand[1] NAND operation rA, rB, rC rA = ~(rB & rC) Stores in rA the negated result of (rB & rC)
nor[1] NOR operation rA, rB, rC rA = ~(rB | rC) Stores in rA the negated result of (rB | rC)
eqv *[1] EQuiValent rA, rB, rC rA = rB == rC Compares if the values of rB and rC are equal and stores the result in rA (?)
andc[1] AND Complement rA, rB, rC rA = rB & ~rC Performs an AND operation on rB and negated rC then stores the result in rA
orc[1] OR Complement rA, rB, rC rA = rB | ~rC Stores in rA the result of (rB | ~rC)
extsb[1] 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[1] 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[1] 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[1] 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[1] Rotate Left Word, aNd with Mask
rlwimi[1] Rotate Left Word Immediate, Mask Insert
Integer Shift Instructions
slw[1] 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[1] 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[1] 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[1] 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[1] Float Move Register fA, fB fA = fB Copies the value of fB into fA (Despite the instruction name, fB is preserved)
fneg[1] Float Negate fA, fB fA = -fB Negates the value of fB and stores the result in fA
fabs[1] Float Absolute fA, fB fA = abs(fB) The absolute value of fB is stored into rA
fnabs[1] 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)[3]
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.


Example: Assume r0 = 29 and r1 = 0x20000000
lmw r0, 0x20(r1)
This will load the following registers like so:
r29 = *(0x20000020)
r30 = *(0x20000024)
r31 = *(0x20000028)

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

rB = rB + iX

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.[4]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.[4]
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 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




  1. 1.00 1.01 1.02 1.03 1.04 1.05 1.06 1.07 1.08 1.09 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 1.19 1.20 1.21 1.22 1.23 1.24 1.25 1.26 1.27 1.28 1.29 1.30 1.31 1.32 1.33 1.34 1.35 1.36 1.37 1.38 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.
  2. 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 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 an o. suffix)
  3. 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.
  4. 4.0 4.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.