Custom Code/PowerPC Assembly Cheatsheet: Difference between revisions

From Zenith
Jump to navigation Jump to search
Content added Content deleted
m (very important line)
(floating point instrs)
Line 7: Line 7:
* If a value is referred to simply as "value" without specifying bit-count, it is implicitly 32 bits (aka a WORD or integer)
* If a value is referred to simply as "value" without specifying bit-count, it is implicitly 32 bits (aka a WORD or integer)
* 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>'''
* <nowiki>#</nowiki> = placeholder
* <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
* 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)
* 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)
* <nowiki>*</nowiki> = unsure of functionality
* <nowiki>*</nowiki> = unsure of exact functionality
{| class="mw-collapsible mw-collapsed" style="min-width: 250px"
{| class="mw-collapsible mw-collapsed" style="min-width: 250px"
|+'''Pseudocode Typedefs'''
|+'''Pseudocode Typedefs'''
!<syntaxhighlight lang="c++">
!<syntaxhighlight lang="c++">
typedef unsigned int uint; // 32 bit value
typedef unsigned int uint; // 32 bit integer value
typedef signed int sint; // 32 bit value
typedef signed int sint; // 32 bit integer value
typedef unsigned short ushort; // 16 bit value
typedef unsigned short ushort; // 16 bit integer value
typedef signed short sshort; // 16 bit value
typedef signed short sshort; // 16 bit integer value
typedef unsigned char ubyte; // 8 bit value
typedef unsigned char ubyte; // 8 bit integer value
typedef signed char sbyte; // 8 bit value
typedef signed char sbyte; // 8 bit integer value
float; // 32 bit floating point value
double; // 64 bit floating point value
</syntaxhighlight>
</syntaxhighlight>
|}
|}
Line 31: Line 34:
!Name
!Name
!Type
!Type
!Bits
!Purpose
!Purpose
|-
|-
| colspan="4" style="text-align: center;" |'''General Purpose Registers (GPRs)'''
| colspan="5" style="text-align: center;" |'''General Purpose Registers (GPRs)'''
|-
|-
|r0
|r0
|GPR0
|GPR0
|Volatile
|Volatile
|32
|General purpose, may be used by function linkage
|General purpose, may be used by function linkage
|-
|-
Line 43: Line 48:
|GPR1
|GPR1
|Unique
|Unique
|32
|Stores the stack pointer
|Stores the stack pointer
|-
|-
Line 48: Line 54:
|GPR2
|GPR2
|Unique
|Unique
|32
|Reserved for the system
|Reserved for the system
|-
|-
Line 53: Line 60:
|GPR3
|GPR3
|Volatile
|Volatile
|32
|Stores 1st argument passed to function calls and their return value
|Stores 1st argument passed to function calls and their return value
|-
|-
Line 58: Line 66:
|GPR4 - GPR10
|GPR4 - GPR10
|Volatile
|Volatile
|32
|Store from 2nd to 8th argument passed to function calls
|Store from 2nd to 8th argument passed to function calls
|-
|-
Line 63: Line 72:
|GPR11 - GPR12
|GPR11 - GPR12
|Volatile
|Volatile
|32
|General purpose, may be used by function linkage
|General purpose, may be used by function linkage
|-
|-
Line 68: Line 78:
|GPR13
|GPR13
|Unique
|Unique
|32
|Stores the small data area pointer
|Stores the small data area pointer
|-
|-
Line 73: Line 84:
|GPR14 - GPR31
|GPR14 - GPR31
|Saved
|Saved
|32
|Store generic integer values and pointers
|Store generic integer values and pointers
|-
|-
| colspan="4" style="text-align: center;" |'''Floating Point Registers (FPRs)'''
| colspan="5" style="text-align: center;" |'''Floating Point Registers (FPRs)'''
|-
|-
|f0
|f0
|FPR0
|FPR0
|Volatile
|Volatile
|64
|Store generic floating point numbers
|Store generic floating point numbers
|-
|-
Line 85: Line 98:
|FPR1
|FPR1
|Volatile
|Volatile
|64
|Stores 1st float argument passed to function calls and their float return value
|Stores 1st float argument passed to function calls and their float return value
|-
|-
Line 90: Line 104:
|FPR2 - FPR8
|FPR2 - FPR8
|Volatile
|Volatile
|64
|Store from 2nd to 8th float argument passed to function calls
|Store from 2nd to 8th float argument passed to function calls
|-
|-
Line 95: Line 110:
|FPR9 - FPR13
|FPR9 - FPR13
|Volatile
|Volatile
|64
|Store generic floating point numbers
|Store generic floating point numbers
|-
|-
Line 100: Line 116:
|FPR14 - FPR30
|FPR14 - FPR30
|Saved
|Saved
|64
|Store generic floating point numbers
|Store generic floating point numbers
|-
|-
Line 105: Line 122:
|FPR31
|FPR31
|Saved
|Saved
|64
|General purpose, used for static chain if needed
|General purpose, used for static chain if needed
|-
|-
| colspan="4" style="text-align: center;" |'''Special Purpose Registers (SPRs)'''
| colspan="5" style="text-align: center;" |'''Special Purpose Registers (SPRs)'''
|-
|-
|PC / IAR
|PC / IAR
|Program Counter / Instruction Address Register
|Program Counter / Instruction Address Register
|Unique
|Unique
|32
|Stores the address of the current instruction (Controlled by the CPU)
|Stores the address of the current instruction (Controlled by the CPU)
|-
|-
Line 117: Line 136:
|Link Register
|Link Register
|Volatile
|Volatile
|32
|Stores the return address for some of the branching instructions
|Stores the return address for some of the branching instructions
|-
|-
Line 122: Line 142:
|CounT Register
|CounT Register
|Volatile
|Volatile
|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
|-
|-
Line 127: Line 148:
|???
|???
|Volatile
|Volatile
|???
|???
|???
|-
|-
|FPSCR
|FPSCR
|Floating Point Status and Control Register
|???
|Volatile
|Volatile
|???
|???
|???
|-
|-
Line 137: Line 160:
|Condition Register 0
|Condition Register 0
|Volatile
|Volatile
|
|Stores a condition
|Stores a condition
|-
|-
Line 142: Line 166:
|Condition Register 1
|Condition Register 1
|Volatile
|Volatile
|
|Stores a condition
|Stores a condition
|-
|-
Line 147: Line 172:
|Condition Registers 2 - 4
|Condition Registers 2 - 4
|Saved
|Saved
|
|Stores a condition
|Stores a condition
|-
|-
Line 152: Line 178:
|Condition Registers 5 - 7
|Condition Registers 5 - 7
|Volatile
|Volatile
|
|Stores a condition
|Stores a condition
|-
|
|
|
|
|
|-
|TODO
|There are way more SPRs than just these...
|
|
|REF: https://wiiubrew.org/wiki/Hardware/Espresso
|}
|}


Line 223: Line 262:
|<code>blr</code>
|<code>blr</code>
|Branch to Link Register
|Branch to Link Register
|N/A
|''N/A''
|<code>return</code>
|<code>return</code>
|Jumps from the current address to the address stored in LR
|Jumps from the current address to the address stored in LR
Line 383: Line 422:
|<code>rA = (int16_t)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
|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, rB is preserved)
|-
|<code>isync</code>
|Instruction SYNChronize
|''N/A''
|
|
|-
|<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>
|<code>lbz</code>
Line 472: Line 535:
|Move To Special Purpose Register
|Move To Special Purpose Register
|<code>SPR, rA</code>
|<code>SPR, rA</code>
|<code>SPR[SPR] = rA</code>
|<code>SPRs[SPR] = rA</code>
|Copies the value of rA into the special purpose register SPR
|Copies the value of rA into the special purpose register SPR
|-
|<code>mtfsf</code> *
|Move To FpScr Fields
|<code>UNK1, fA</code>
|
|Copies the value of fA into the FPSCR under the control of the field mask in UNK1
|-
|<code>mtfsb1</code>
|Move To FpScr Bit 1
|<code>iX<sub>?</sub></code>
|<code><nowiki>FPSCR = FPSCR | 0b1 << iX - 1</nowiki></code>
|Sets bit iX of the FPSCR register to 1
|-
|-
|<code>mulli</code>
|<code>mulli</code>
Line 589: Line 664:
|Shifts the value in rB by iX to the right and stores the result in rA
|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
Unlike regular zero-fill right shift operations, this one sign-fills the vacant bits
|-
|<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>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>stb</code>
|<code>stb</code>

Revision as of 09:10, 22 September 2022

Instructions, registers and general info cheatsheet for PowerPC 32-bit Big Endian Assembly architecture used by the Wii U.

How to read 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 or integer)
  • 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>
  • # = 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)
  • * = unsure of exact functionality
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 Type Bits Purpose
General Purpose Registers (GPRs)
r0 GPR0 Volatile 32 General purpose, may be used by function linkage
r1 GPR1 Unique 32 Stores the stack pointer
r2 GPR2 Unique 32 Reserved for 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 32 General purpose, may be used by function linkage
r13 GPR13 Unique 32 Stores the small data area pointer
r14 - r31 GPR14 - GPR31 Saved 32 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 Unique 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
XER ??? Volatile ??? ???
FPSCR Floating Point Status and Control Register Volatile ??? ???
cr0 Condition Register 0 Volatile Stores a condition
cr1 Condition Register 1 Volatile Stores a condition
cr2 - cr4 Condition Registers 2 - 4 Saved Stores a condition
cr5 - cr7 Condition Registers 5 - 7 Volatile Stores a condition
TODO There are way more SPRs than just these... REF: https://wiiubrew.org/wiki/Hardware/Espresso
Instructions
Instruction Name Parameters Pseudocode Equivalent Additional Info
add ADD operation 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
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
and AND Operation rA, rB, rC rA = rB & rC Performs an AND operation on rB and rC then stores the result in rA
andc AND Complement rA, rB, rC rA = rB & ~rC Performs an AND operation on rB and negated rC then stores the result in rA
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
b Branch iX₂₄ goto LABEL Jumps from the current address to IAR + iX, either up or down
bl Branch and 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 it in LR

This is the most common instruction to use for calling a function

blr Branch to Link Register N/A return Jumps from the current address to the address stored in LR

This is essentially the return statement of a function

beq Branch if EQual
bne Branch if Not Equal
bgt Branch if Greater Than
blt Branch if Less Than
ble Branch if Less than or Equal
bge Branch if Greater than or Equal
bng Branch if Not Greater than
bnl Branch if Not Less than
bso Branch if Summary Overflow ??? ??? Unknown
bns Branch if Not Summary overflow ??? ??? Unknown
bun Branch if UNordered ??? ??? Unknown
bnu Branch if Not Unordered ??? ??? Unknown
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
cmp CoMPare
cmpwi CoMPare Word Immediate
cmplwi CoMPare Logical Word Immediate
cntlzw CouNT Leading Zeros Word
eieio Enforce In-order Execution of I/O ??? ??? Unknown
eqv EQuiValent rA, rB, rC rA = rB == rC Compares if the values of rB and rC are equal and stores the result in rA (?)
extsb 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 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
fmr Float Move Register fA, fB fA = fB Copies the value of fB into fA (Despite the instruction name, rB is preserved)
isync Instruction SYNChronize N/A
lfs Load Float Single fA, iX₁₆(rA) fA = (float)(*(rA + iX)) Loads the value at the address (rA + iX) casted to float into fA.
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.
lbz Load Byte Zero-fill rA, iX₁₆(rB) rA = (ubyte)(*(rB + iX)) Loads the 8 bit value at the address (rB + iX) into rA
lhz Load Halfword Zero-fill rA, iX₁₆(rB) rA = (ushort)(*(rB + iX)) Loads the 16 bit value at the address (rB + iX) into rA
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
lwz Load Word Zero-fill rA, iX₁₆(rB) rA = *(rB + iX) Loads the value at the address (rB + iX) into rA
lwzu Load Word Zero 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)
lwzx Load Word Zero indeXed rA, rB, rC rA = *(rB + rC) Loads the value at the address (rB + rC) into rA
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)

mr Move Register rA, rB rA = rB Copies the value of rB into rA (Despite the instruction name, rB is preserved)
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
mtspr Move To Special Purpose Register SPR, rA SPRs[SPR] = rA Copies the value of rA into the special purpose register SPR
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
mulli MULtiply Low Immediate rA, rB, iX₁₆ rA = rB * iX Multiplies the value of rB by iX and stores the result in rA
nand NAND operation rA, rB, rC rA = ~(rB & rC) Stores in rA the negated result of (rB & rC)
neg NEGate rA, rB rA = ~rB + 1 Stores in rA the result of negated rB with 1 added to it's value afterwards
nor NOR operation rA, rB, rC rA = ~(rB | rC) Stores in rA the negated result of (rB | rC)
not NOT operation rA, rB rA = ~rB Stores in rA the result of negated rB
or OR operation rA, rB, rC rA = rB | rC Stores in rA the result of (rB | rC)
orc OR Complement rA, rB, rC rA = rB | ~rC Stores in rA the result of (rB | ~rC)
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))
rlwinm Rotate Left Word Immediate aNd 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

sc System Call iX₇ N/A Calls upon the system to perform a service identified by iX
slw 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
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
srw 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
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
sraw 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

srawi 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

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)
stfd STore Float Double fA, iX₁₆(rA) *(rA + iX) = fA Stores the 64 bit value of fA at the memory address (rA + iX)
stb STore Byte rA, iX₁₆(rB) *(rB + iX) = (ubyte)rA Stores the 8 bit value of rA at the memory address (rB + iX)
sth STore Halfword rA, iX₁₆(rB) *(rB + iX) = (ushort)rA Stores the 16 bit value of rA at the memory address (rB + iX)
stw STore Word rA, iX₁₆(rB) *(rB + iX) = rA Stores the value of rA at the memory address (rB + iX)
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

stwx STore Word indeXed rA, rB, rC *(rB + rC) = rA Stores the value of rA at the memory address (rB + rC)
stmw * STore Multiple Words
xor XOR operation rA, rB, rC rA = rB ^ rC Performs an XOR operation on rB and rC then stores the result in rA
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

External Resources