Custom Code/PowerPC Assembly Cheatsheet: Difference between revisions
Jhmaster2000 (talk | contribs) mNo edit summary |
Jhmaster2000 (talk | contribs) (pr0gress) |
||
Line 1: | Line 1: | ||
= '''// WIP''' = |
= '''// WIP''' = |
||
if a right shift operation does not specify it is sign-fill, it is implicitly zero-fill by default |
|||
<nowiki>#</nowiki> = placeholder |
<nowiki>#</nowiki> = placeholder |
||
Line 9: | Line 11: | ||
<nowiki>*</nowiki> = unsure of functionality |
<nowiki>*</nowiki> = unsure of functionality |
||
IAR = Instruction Address Register (current address) |
|||
LR = Link Register |
|||
All special registers (TODO) |
|||
resources: |
resources: |
||
Line 15: | Line 23: | ||
* http://wiibrew.org/wiki/Assembler_Tutorial#Load_and_Store_Instructions (also has missing instructions but way more accurate and better worded) |
* http://wiibrew.org/wiki/Assembler_Tutorial#Load_and_Store_Instructions (also has missing instructions but way more accurate and better worded) |
||
* http://math-atlas.sourceforge.net/devel/assembly/ppc_isa.pdf (official instruction set docs, hard to navigate/search) |
* http://math-atlas.sourceforge.net/devel/assembly/ppc_isa.pdf (official instruction set docs, hard to navigate/search) |
||
*https://arcb.csc.ncsu.edu/~mueller/cluster/ps3/SDK3.0/docs/arch/PPC_Vers202_Book3_public.pdf (extension of the above, even more instructions and some in even more technical detail) |
|||
pseudocode typedefs:<syntaxhighlight lang="c++"> |
|||
typedef unsigned int uint; |
|||
typedef signed int sint; |
|||
typedef unsigned short ushort; |
|||
typedef signed short sshort; |
|||
typedef unsigned char ubyte; |
|||
typedef signed char sbyte; |
|||
</syntaxhighlight> |
|||
{| class="wikitable" |
{| class="wikitable" |
||
|- |
|- |
||
Line 23: | Line 40: | ||
!Additional Info |
!Additional Info |
||
|- |
|- |
||
|<code>add</code> |
|||
|li |
|||
|ADD operation |
|||
|Load Immediate |
|||
|rA, |
|<code>rA, rB, rC</code> |
||
|<code>rA = iX</code> |
|||
|Loads iX into rA |
|||
|- |
|||
|lis |
|||
|Load Immediate Shifted |
|||
|rA, iX₁₆ |
|||
| `rA="rA" |<code><nowiki>rA = rA | (iX << 16)</nowiki></code> |
|||
|Loads iX into the upper 16 bits of rA |
|||
|- |
|||
|lwz |
|||
|Load Word Zero |
|||
|rA, iX₁₆(rB) |
|||
|<code>rA = *(rB + iX)</code> |
|||
|Loads the value at the address (rB + iX) into rA |
|||
|- |
|||
|lwzu |
|||
|Load Word Zero Update |
|||
|rA, iX₁₆(rB) |
|||
|<code>rA = *(rB + iX)<br />rB = rB + iX</code> |
|||
|Loads the value at the address (rB + iX) into rA<br />Then loads rB with the address (rB + iX) |
|||
|- |
|||
|lwzx |
|||
|Load Word Zero Indexed |
|||
|rA, rB, rC |
|||
|<code>rA = *(rB + rC)</code> |
|||
|Loads the value at the address (rB + rC) into rA |
|||
|- |
|||
|lmw * |
|||
|Load Multiple Words |
|||
|rA, iX₁₆(rB) |
|||
|<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<br />address (rB + iX + N), where N starts at 0 and<br />increments by 4 for each register loaded.<br /><br />Example: (r0 = 29, 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> |
|||
|- |
|||
|add |
|||
|Addition |
|||
|rA, rB, rC |
|||
|<code>rA = rB + rC</code> |
|<code>rA = rB + rC</code> |
||
|Adds the values of rB and rC together and stores the result in rA |
|||
| |
|||
|- |
|- |
||
|addi |
|<code>addi</code> |
||
| |
|ADD Immediate |
||
|rA, rB, iX₁₆ |
|<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 |
|||
| |
|||
|- |
|- |
||
|addis |
|<code>addis</code> |
||
| |
|ADD Immediate Shifted |
||
|rA, rB, iX₁₆ |
|<code>rA, rB, iX₁₆</code> |
||
|<code>rA = rB + (iX << 16)</code> |
|<code>rA = rB + (iX << 16)</code> |
||
|Adds the values of rB and (iX << 16) together and stores the result in rA |
|||
| |
|||
|- |
|- |
||
|and |
|<code>and</code> |
||
|AND Operation |
|AND Operation |
||
|rA, rB, rC |
|<code>rA, rB, rC</code> |
||
|<code>rA = rB & rC</code> |
|<code>rA = rB & rC</code> |
||
|Performs an AND operation on rB and rC then stores the result in rA |
|||
| |
|||
|- |
|- |
||
|andc |
|<code>andc</code> |
||
|AND Complement |
|AND Complement |
||
|rA, rB, rC |
|<code>rA, rB, rC</code> |
||
|<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 |
|||
| |
|||
|- |
|- |
||
|andi. |
|<code>andi.</code> |
||
|AND Immediate |
|AND Immediate |
||
|rA, rB, uiX₁₆ |
|<code>rA, rB, uiX₁₆</code> |
||
|<code>rA = rB & uiX</code> |
|<code>rA = rB & uiX</code> |
||
|Performs an AND operation on rB and uiX then stores the result in rA |
|||
| |
|||
|- |
|- |
||
|andis. |
|<code>andis.</code> |
||
|AND Immediate Shifted |
|AND Immediate Shifted |
||
|rA, rB, uiX₁₆ |
|<code>rA, rB, uiX₁₆</code> |
||
|< |
|<code>rA = rB & (uiX << 16)</code> |
||
|Performs an AND operation on rB and (uiX << 16) then stores the result in rA |
|||
| |
|||
|- |
|- |
||
|<code>b</code> |
|||
|b |
|||
|Branch |
|Branch |
||
|<code>iX₂₄</code> |
|||
| |
|||
|<code>goto LABEL</code> |
|||
| |
|||
|Jumps from the current address to IAR + iX, either up or down |
|||
| |
|||
|- |
|- |
||
|<code>bl</code> |
|||
|bl |
|||
|Branch |
|Branch and Link |
||
|<code>iX₂₄</code> |
|||
| |
|||
|<code>((void (*)())IAR + iX)()</code> |
|||
| |
|||
|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 |
|<code>blr</code> |
||
|Branch |
|Branch to Link Register |
||
| |
|N/A |
||
|<code>return</code> |
|||
| |
|||
|Jumps from the current address to the address stored in LR |
|||
| |
|||
This is essentially the '''return''' statement of a function |
|||
|- |
|- |
||
|beq |
|<code>beq</code> |
||
|Branch |
|Branch if EQual |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|bne |
|<code>bne</code> |
||
|Branch |
|Branch if Not Equal |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|bgt |
|<code>bgt</code> |
||
|Branch |
|Branch if Greater Than |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|blt |
|<code>blt</code> |
||
|Branch |
|Branch if Less Than |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|ble |
|<code>ble</code> |
||
|Branch |
|Branch if Less than or Equal |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|bge |
|<code>bge</code> |
||
|Branch |
|Branch if Greater than or Equal |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|bng |
|<code>bng</code> |
||
|Branch |
|Branch if Not Greater than |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|bnl |
|<code>bnl</code> |
||
|Branch |
|Branch if Not Less than |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|bso |
|<code>bso</code> |
||
|Branch |
|Branch if Summary Overflow |
||
| |
|??? |
||
| |
|??? |
||
|Unknown |
|||
| |
|||
|- |
|- |
||
|bns |
|<code>bns</code> |
||
|Branch |
|Branch if Not Summary overflow |
||
| |
|??? |
||
| |
|??? |
||
|Unknown |
|||
| |
|||
|- |
|- |
||
|bun |
|<code>bun</code> |
||
|Branch |
|Branch if UNordered |
||
| |
|??? |
||
| |
|??? |
||
|Unknown |
|||
| |
|||
|- |
|- |
||
|bnu |
|<code>bnu</code> |
||
|Branch |
|Branch if Not Unordered |
||
| |
|??? |
||
| |
|??? |
||
|Unknown |
|||
| |
|||
|- |
|- |
||
|bctr |
|<code>bctr</code> |
||
|Branch |
|Branch to CounT Register |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|bctrl |
|<code>bctrl</code> |
||
|Branch |
|Branch to CounT Register and Link |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|bdnz |
|<code>bdnz</code> |
||
|Branch |
|Branch if Decremented count register Not Zero |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|bdnzt |
|<code>bdnzt</code> |
||
|Branch |
|Branch if Decremented count register Not Zero and if condition True |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|bdnzf |
|<code>bdnzf</code> |
||
|Branch |
|Branch if Decremented count register Not Zero and if condition False |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|bdz |
|<code>bdz</code> |
||
|Branch if Decremented |
|Branch if Decremented count register Zero |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|cmp |
|<code>cmp</code> |
||
|CoMPare |
|||
|Compare |
|||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|cmpwi |
|<code>cmpwi</code> |
||
| |
|CoMPare Word Immediate |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|cmplwi |
|<code>cmplwi</code> |
||
| |
|CoMPare Logical Word Immediate |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|cntlzw |
|<code>cntlzw</code> |
||
| |
|CouNT Leading Zeros Word |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|eieio |
|<code>eieio</code> |
||
|Enforce In- |
|Enforce In-order Execution of I/O |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|eqv |
|<code>eqv</code> |
||
|EQuiValent |
|||
|Equivalent |
|||
|rA, rB, rC |
|<code>rA, rB, rC</code> |
||
|<code>rA = rB == rC</code> |
|<code>rA = rB == rC</code> |
||
| |
| |
||
|- |
|- |
||
|extsb |
|<code>extsb</code> |
||
| |
|EXTend Sign Byte |
||
|rA, rB |
|<code>rA, rB</code> |
||
|<code>rA = (int8_t)rB</code> |
|<code>rA = (int8_t)rB</code> |
||
| |
| |
||
|- |
|- |
||
|extsh |
|<code>extsh</code> |
||
| |
|EXTend Sign Halfword |
||
|rA, rB |
|<code>rA, rB</code> |
||
|<code>rA = (int16_t)rB</code> |
|<code>rA = (int16_t)rB</code> |
||
| |
| |
||
|- |
|- |
||
|extsw |
|<code>extsw</code> |
||
| |
|EXTend Sign Word |
||
|rA, rB |
|<code>rA, rB</code> |
||
|<code>rA = (int32_t)rB</code> |
|<code>rA = (int32_t)rB</code> |
||
| |
| |
||
|- |
|- |
||
|<code>li</code> |
|||
|mr |
|||
|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 |
|||
|<code>rA, iX₁₆(rB)</code> |
|||
|<code>rA = *(rB + iX)</code> |
|||
|Loads the value at the address (rB + iX) 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 |
|Move Register |
||
|rA, rB |
|<code>rA, rB</code> |
||
|<code>rA = rB</code> |
|<code>rA = rB</code> |
||
| |
| |
||
|- |
|- |
||
|mflr |
|<code>mflr</code> |
||
|Move From Link Register |
|Move From Link Register |
||
| |
| |
||
Line 299: | Line 327: | ||
| |
| |
||
|- |
|- |
||
|mtlr |
|<code>mtlr</code> |
||
|Move To Link Register |
|Move To Link Register |
||
| |
| |
||
Line 305: | Line 333: | ||
| |
| |
||
|- |
|- |
||
|mtctr |
|<code>mtctr</code> |
||
|Move To |
|Move To CounT Register |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|mtspr |
|<code>mtspr</code> |
||
|Move To Special Purpose Register |
|Move To Special Purpose Register |
||
| |
| |
||
Line 317: | Line 345: | ||
| |
| |
||
|- |
|- |
||
|mulli |
|<code>mulli</code> |
||
| |
|MULtiply Low Immediate |
||
| |
| |
||
| |
| |
||
| |
| |
||
|- |
|- |
||
|nand |
|<code>nand</code> |
||
|NAND |
|NAND operation |
||
|rA, rB, rC |
|<code>rA, rB, rC</code> |
||
|<code>rA = ~(rB & rC)</code> |
|<code>rA = ~(rB & rC)</code> |
||
| |
| |
||
|- |
|- |
||
|neg |
|<code>neg</code> |
||
|NEGate |
|||
|Negate |
|||
|rA, rB |
|<code>rA, rB</code> |
||
|<code>rA = ~rB + 1</code> |
|<code>rA = ~rB + 1</code> |
||
| |
| |
||
|- |
|- |
||
|nor |
|<code>nor</code> |
||
|NOR |
|NOR operation |
||
|rA, rB, rC |
|<code>rA, rB, rC</code> |
||
| `rA="~(rB" |<code><nowiki>rA = ~(rB | rC)</nowiki></code> |
| `rA="~(rB" |<code><nowiki>rA = ~(rB | rC)</nowiki></code> |
||
| |
| |
||
|- |
|- |
||
|not |
|<code>not</code> |
||
|NOT |
|NOT operation |
||
|rA, rB |
|<code>rA, rB</code> |
||
|<code>rA = ~rB</code> |
|<code>rA = ~rB</code> |
||
| |
| |
||
|- |
|- |
||
|<code>or</code> |
|||
|or |
|||
|OR |
|OR operation |
||
|rA, rB, rC |
|<code>rA, rB, rC</code> |
||
| `rA="rB" |<code><nowiki>rA = rB | rC</nowiki></code> |
| `rA="rB" |<code><nowiki>rA = rB | rC</nowiki></code> |
||
| |
| |
||
|- |
|- |
||
|orc |
|<code>orc</code> |
||
|OR Complement |
|OR Complement |
||
|rA, rB, rC |
|<code>rA, rB, rC</code> |
||
| `rA="rB" |<code><nowiki>rA = rB | ~rC</nowiki></code> |
| `rA="rB" |<code><nowiki>rA = rB | ~rC</nowiki></code> |
||
| |
| |
||
|- |
|- |
||
|ori |
|<code>ori</code> |
||
|OR Immediate |
|OR Immediate |
||
|rA, rB, iX₁₆ |
|<code>rA, rB, iX₁₆</code> |
||
| `rA="rB" |<code><nowiki>rA = rB | iX</nowiki></code> |
| `rA="rB" |<code><nowiki>rA = rB | iX</nowiki></code> |
||
| |
| |
||
|- |
|- |
||
|oris |
|<code>oris</code> |
||
|OR Immediate Shifted |
|OR Immediate Shifted |
||
|rA, rB, iX₁₆ |
|<code>rA, rB, iX₁₆</code> |
||
| `rA="rB" |<code><nowiki>rA = rB | (iX << 16)</nowiki></code> |
| `rA="rB" |<code><nowiki>rA = rB | (iX << 16)</nowiki></code> |
||
| |
| |
||
|- |
|- |
||
|rlwinm |
|<code>rlwinm</code> |
||
|Rotate Left Word Immediate |
|Rotate Left Word Immediate aNd Mask |
||
|<code>rA, rB, iX₅, iY₅, 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>sc</code> |
|||
|System Call |
|||
|<code>iX₇</code> |
|||
|N/A |
|||
|Calls upon the system to perform a service identified by iX |
|||
|- |
|- |
||
|slw |
|<code>slw</code> |
||
|Shift Left Word |
|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 |
|||
| |
|||
|- |
|- |
||
|slwi |
|<code>slwi</code> |
||
|Shift Left Word Immediate |
|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>srw</code> |
|||
|sraw |
|||
|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> |
|||
|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 |
|||
|- |
|||
|<code>sraw</code> |
|||
|Shift Right Algebraic Word |
|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>srawi</code> |
|||
|stwu |
|||
|Shift Right Algebraic Word Immediate |
|||
|Store Word And Update |
|||
|<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>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>stwu</code> |
|||
|xor |
|||
|STore Word And Update |
|||
|XOR Operation |
|||
|rA, rB |
|<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> |
|||
|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>xor</code> |
|||
|XOR operation |
|||
|<code>rA, rB, rC</code> |
|||
|<code>rA = rB ^ rC</code> |
|<code>rA = rB ^ rC</code> |
||
|Performs an XOR operation on rB and rC then stores the result in rA |
|||
| |
|||
|- |
|- |
||
|xori |
|<code>xori</code> |
||
|XOR Immediate |
|XOR Immediate |
||
|rA, rB, iX₁₆ |
|<code>rA, rB, iX₁₆</code> |
||
|<code>rA = rB ^ iX</code> |
|<code>rA = rB ^ iX</code> |
||
|Performs an XOR operation on rB and iX then stores the result in rA |
|||
| |
|||
|- |
|- |
||
|xoris |
|<code>xoris</code> |
||
|XOR Immediate Shifted |
|XOR Immediate Shifted |
||
|rA, rB, iX₁₆ |
|<code>rA, rB, iX₁₆</code> |
||
|<code>rA = rB ^ (iX << 16)</code> |
|<code>rA = rB ^ (iX << 16)</code> |
||
|Performs an XOR operation on rB and (iX << 16) then stores the result in rA |
|||
| |
|||
|} |
|} |
||
Revision as of 07:45, 29 May 2022
// WIP
if a right shift operation does not specify it is sign-fill, it is implicitly zero-fill by default
# = placeholder
r# = register
i# = immediate (the subscript numbers next to it is it's size in bits)
ui# = unsigned immediate (above is signed)
* = unsure of functionality
IAR = Instruction Address Register (current address)
LR = Link Register
All special registers (TODO)
resources:
- https://jimkatz.github.io/powerpc_for_dummies (very incomplete, has mistakes)
- http://wiibrew.org/wiki/Assembler_Tutorial#Load_and_Store_Instructions (also has missing instructions but way more accurate and better worded)
- http://math-atlas.sourceforge.net/devel/assembly/ppc_isa.pdf (official instruction set docs, hard to navigate/search)
- https://arcb.csc.ncsu.edu/~mueller/cluster/ps3/SDK3.0/docs/arch/PPC_Vers202_Book3_public.pdf (extension of the above, even more instructions and some in even more technical detail)
pseudocode typedefs:
typedef unsigned int uint;
typedef signed int sint;
typedef unsigned short ushort;
typedef signed short sshort;
typedef unsigned char ubyte;
typedef signed char sbyte;
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 | |||
eqv
|
EQuiValent | rA, rB, rC
|
rA = rB == rC
|
|
extsb
|
EXTend Sign Byte | rA, rB
|
rA = (int8_t)rB
|
|
extsh
|
EXTend Sign Halfword | rA, rB
|
rA = (int16_t)rB
|
|
extsw
|
EXTend Sign Word | rA, rB
|
rA = (int32_t)rB
|
|
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 | 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.
|
mr
|
Move Register | rA, rB
|
rA = rB
|
|
mflr
|
Move From Link Register | |||
mtlr
|
Move To Link Register | |||
mtctr
|
Move To CounT Register | |||
mtspr
|
Move To Special Purpose Register | |||
mulli
|
MULtiply Low Immediate | |||
nand
|
NAND operation | rA, rB, rC
|
rA = ~(rB & rC)
|
|
neg
|
NEGate | rA, rB
|
rA = ~rB + 1
|
|
nor
|
NOR operation | rA, rB, rC
|
rA = ~(rB | rC)
|
|
not
|
NOT operation | rA, rB
|
rA = ~rB
|
|
or
|
OR operation | rA, rB, rC
|
rA = rB | rC
|
|
orc
|
OR Complement | rA, rB, rC
|
rA = rB | ~rC
|
|
ori
|
OR Immediate | rA, rB, iX₁₆
|
rA = rB | iX
|
|
oris
|
OR Immediate Shifted | rA, rB, iX₁₆
|
rA = 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 |
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
|
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) |
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 |