Beginner's Simple ASM Reference Page
This reference page is for beginner ASM Coders. It covers most instructions that are suitable for beginner-level Assembly work. It does include some 'intermediate level' stuff. Therefore, if you are a Beginner and some of the stuff confuses you, you can always visit this page back later after you have gained more ASM knowledge/experience.
Advanced ASM Coders have basically no need for this page, as they should be knowledgeable enough to decipher a 'professional' level PPC-based User's Manual.
General overview:
Notes for Syntax format:
Load Immediate
li rD, SIMM
Loads SIMM into rD.
li r3, 0x00CC
Loads the immediate value 0x00CC into r3. r3 is now 0x000000CC.
Nop
This instruction will literally make the CPU do nothing. Nop is short for No-Operation. Some C2 Insert ASM Codes may have a nop added at the very end (by the ASM Assembler) as the source of any C2 ASM Code needs to have an odd amount of instructions.
Example:
li r0, 1
stw r0, 0 (r12)
nop
Add
add rD, rA, rB
The result of rA + rB is placed into rD.
add r6, r5, r4
If..
r5 = 4
r4 = 5
Then r6 would equal 0x00000009
Subtract
sub rD, rA, rB
The result of rA - rB is placed into rD.
sub r12, r11, r4
If..
r11 = 0
r4 = 4
Then r12 would equal -4 (0xFFFFFFFC)
Add Immediate
addi rD, rA, SIMM
The result of rA + SIMM is placed into rD. If rA = r0, then rA is treated as literal 0.
addi r6, r5, 2
If..
r5 = 4
Then r6 would equal 0x00000006
Subtract Immediate
subi rD, rA, SIMM
The result of rA - SIMM is placed into rD. If rA = r0, then rA is treated as literal 0.
subi r30, r16, 1
If..
r16 = 1
Then r30 would equal zero.
Load Immediate Shifted
lis rD, UIMM
Loads UIMM into the upper 16 bits of rD. Lower 16 bits of rD are cleared (zeroed)
lis r12, 1
Loads the immediate value of 1 into the upper 16 bits of r12, lower 16 bits are cleared. r12 is now 0x00010000
Or Immediate
ori rD, rA, UIMM
For most uses in Assembly Codes, ori is used along with lis to write a complete word value to a register.
Example:
lis r4, 0x8000
ori r4, r4, 0x15EC
r4 is now 0x800015EC
Add Immediate Shifted
addis rD, rA, UIMM
UIMM (as VVVV0000) is added to rA. The result is placed into rD. Therefore, the lower bits of rA will always be 'copied' over to rD in any addis instruction. If rA = r0, then rA is treated as literal 0.
addis r6, r5, 2
If..
r5 = 4
Then r6 would equal 0x00020004.
Subtract Immediate Shifted
subis rD, rA, SIMM
The result of rA minus SIMM (as VVVV0000) is placed into rD. Therefore, the lower bits of rA will always be 'copied' over to rD in any subis instruction. If rA = r0, then rA is treated as literal 0.
subis r11, r7, 0x2000
If..
r7 = 0x10005555
Then r11 would equal 0xF0005555.
Store Word
stw rD, SIMM (rA)
Word value in rD is stored to the memory address designated by SIMM+rA. If rA = r0, then rA is treated as literal 0.
stw r3, 0x0002 (r4)
If..
r3 = 0x00000005
r4 = 0x80001574
Then the word at Memory Address 0x80001576 is now 0x00000005.
Store Halfword
sth rD, SIMM (rA)
Halfword value in rD is stored to the memory address designated by SIMM+rA. If rA = r0, then rA is treated as literal 0.
sth r3, 0x0002 (r4)
If..
r3 = 0x00000005
r4 - 0x80001574
Then the halfword at Memory Address 0x80001576 is now 0x0005.
Store Byte
stb rD, SIMM (rA)
Byte value in rD is stored to the memory address designed by SIMM+rA. If rA = r0, then rA is treated as literal 0.
stb r3, 0x0002 (r4)
If..
r3 = 0x00000005
r4 = 0x80001574
Then the byte at Memory Address 0x80001576 is now 0x05.
Load Word & Zero
lwz rD, SIMM (rA)
The word value in Memory located at SIMM+rA is loaded into rD. If rA = r0, then rA is treated as literal 0.
lwz r3, 0x0002 (r4)
If...
r4 = 0x80001574
& Word value at Memory Address 0x80001576 is 0x1500FFFF
Then r3 would equal 0x1500FFFF.
Load Halfword & Zero
lhz rD, SIMM (rA)
The halfword value in Memory located at SIMM+rA is loaded into rD. Upper 16 bits of rD are cleared (zeroed). If rA = r0, then rA is treated as literal 0.
lhz r3, 0x0002 (r4)
If..
r4 = 0x80001574
& Halfword value at Memory Address 0x80001576 is 0x1500
Then r3 would equal 0x00001500.
Load Byte & Zero
lbz rD, SIMM (rA)
The byte value in Memory located at SIMM+rA is loaded in rD. The left-hand side 3 bytes of rD are cleared (zeroed). If rA = r0, then rA is treated as literal 0.
lbz r3, 0x0002 (r4)
If..
r4 = 0x80001574
& Byte value at Memory Address 0x80001576 = 0x15
Then r3 would equal 0x00000015.
Move Register
mr rD, rA
Value of rA is copied to rD.
mr r4, r3
If..
r3 = 0xFFFFFFD0
Then r4 = 0xFFFFFFD0.
Multiply Low Word Signed
mullw rD, rA, rB
Signed
The result of rA x rB is placed into rD. The multiplication is Signed. If the result exceeded a 32-bit sized value, then only the lower 32 bits of said value are used as the result in rD.
mullw r9, r3, r0
If...
r0 = 0x00000005
r3 = 0x0000000B
Then r9 would equal 0x00000037
Multiply Immediate Signed
mulli rD, rA, SIMM
Signed
Thre result of rA x rB is placed into rD. The multiplication is Signed. If the result exceeded a 32-bit sized value, then only the lower 32 bits of said value are used as the result in rD>
mulli r10, r10, 0x0004
If..
r10 = 0x0000000C
Then r10 would equal 0x00000030
Divide Word Signed
divw rD, rA, rB
Signed
The result of rA / rB is placed into rD. The division is Signed. If rounding is needed, the number will round *DOWN* to the closest whole number. Let's pretend you executed a divw instruction that had a result of 1.9 (0x1.E66~ in Hex), the result placed into rD will be 1.
divw r4, r30, r15
If..
r30 = 0xFFFFFFFC
r15 = 0x00000002
Then r4 would equal 0xFFFFFFFE.
Divide Word Unsigned/Logical
divwu rD, rA, rB
Unsigned/Logical
The result of rA / rB is placed in rD. The division is Unsigned and thus, all values are treated as positive. If rounding is needed, the number will round *DOWN* to the closest whole number.
divwu r4, r30, r15
If..
r30 = 0xFFFFFFFC
r15 = 0x00000002
Then r4 would equal 0x7FFFFFFE.
Branch
b SIMM
The execution of the CPU will jump forward/backward based on the amount designated in SIMM. SIMM must be divisible by 4. If SIMM is positive then the CPU jumps 'down', visually speaking. If SIMM is negative, then the CPU jumps 'back up'. If SIMM is zero, the CPU simply halts.
For Assembly Codes, branch labels (SIMM is replaced with a custom name) are used instead of writing out the Signed 16-bit Immediate Value (SIMM).
Example:
b the_label
li r5, 0
the_label:
stb r5, 0 (r12)
The instruction where the Brancj jump lands at is also present but needs to have a colon appended. The 'li r5, 0' instruction is skipped because the branch above to jumping to 'the_label' which is pointing to the stb instruction.
Branch If Equal
beq SIMM
If the previous comparison instruction had a condition where the result was equal, then the branch will be taken. Branch labels (custom names) are used in place of SIMM.
Example code showing use of beq instruction
cmpwi r5, 3
beq some_label
li r0, 9
some_label:
stw r0, 0 (r12)
beq is part of a large family of Conditional Branch Instructions.
List of other commonly used Conditional Branches~
bgt = Branch If Greater Than
blt = Branch If Less Than
ble = Branch If Less Than Or Equal
bge = Branch If Greater Than Or Equal
Compare Word Immediate Signed
cmpwi rD, SIMM
Signed
Value in rD is compared to SIMM. The comparison is Signed. A conditional branch should be placed afterwards to branch based on the result of the comparison.
Compare Word Signed
cmpw rD, rA
Signed
Value in rD is compared to value in rA. The comparison is Signed. A conditional branch should be placed afterwards to branch based on the result of the comparison.
Compare Logical Word Immediate Unsigned/Logical
cmplwi rD, UIMM
Logical
Value in rD is compared to UIMM, the comparison is unsigned. All values are treated as unsigned. A conditional branch should be placed afterwards to branch based on the result of the comparison.
Compare Logical Word Unsigned/Logical
cmplw rD, rA
Logical
Value in rD is compared to value in rA, the comparison is unsigned. All values are treated as unsigned. A conditional branch should be placed afterwards to branch based on the result of the comparison.
Store Word Indexed
stwx rD, rA, rB
The word value of rD is stored to the Memory Address designated by rA + rB. If rA = r0, then it is treated as literal zero.
stwx r12, r12, r29
If...
r12 = 0x00000200
r29 = 0x80001000
Then the word at Memory Address 0x80001200 is now 0x00000200.
sthx is for halfwords, stbx is for bytes
Load Word & Zero Indexed
lwzx rD, rA, rB
The word value located at the Memory Address designated by rA + rB is loaded into rD. If rA = r0, then it is treated as literal zero.
lwzx r30, r4, r16
If...
r4 = 0x00000008
r16 = 0x80005000
& word value at Memory Address 0x80005008 is 0x000000FF
Then r30 would equal 0x000000FF.
lhzx is for halfwords, lbzx is for bytes
Move to Count Register
mtctr rD
The value in rD is copied to the Count Register (CTR).
Move from the Count Register
mfctr rD
The value in the Count Register (CTR) is copied to rD
Branch Decrement When Not Zero
bdnz SIMM
The count register is subtracted by 1 (aka decremented), then the count register is compared to the value of 0. If the count register is not zero, the branch is taken. For assembly codes, the use of label names replace SIMM. SIMM must be divisible by 4, this is not a concern for Coders if they stick to using branch label names.
This instruction is used to make loops (along with the mtctr instruction).
Move To Link Register
mtlr rD
The value rD is copied to the Link Register (LR).
Move From Link Register
mflr rD
The value in the Link Register (LR) is copied to Register rD
Branch & Link
bl SIMM
An unconditional branch is executed, the amount the branch 'jumps' is based on SIMM. SIMM must be divisible by 4. This won't be an issue for you if you use branch labels. After the branch has been executed, the address of the branch instruction+4 is written to the Link Register.
This instruction is used mainly for creating subroutines in your code.
Example showing mem addresses and instructions~
80456124 : bl 0x1F8C
80456128 : cmpwi r3, 0
8045612C : add r5, r3, r4
Once the 'bl 0x1F8C' instruction has executed, the Link Register will now contain 80456128.
Branch to Link Register
blr
Execution of the CPU will branch/jump to the Memory Address that's in the Link Register.
Branch to Count Register
bctr
Execution of the CPU will branch/jump to the Memory Address that's in the Count Register.
Store Multiple Word
stmw rD, SIMM (rA)
Multiple words are stored starting at Memory Address designated by SIMM+rA. If rA = r0, then it is treated at literal 0. SIMM+rA must be divisible by 4.
The amount of words stored is based on which GPR for rD is used.
If rD is r30, then...
r30's word value is stored to SIMM+rA
r31's word value is stored to SIMM+rA+4
If rD is 25, then...
r25's word value is stored to SIMM+rA
r26's word value is stored to SIMM+rA+4
r27's word value is stored to SIMM+rA+8
r28's word value is stored to SIMM+rA+12
r29's word value is stored to SIMM+rA+16
r30's word value is stored to SIMM+rA+20
r31's word value is stored to SIMM+rA+24
Using this instruction when rD = r31 is pointless, since a basic stw instruction can be used instead.
Example:
stmw r29, 0x00EC (r5)
If..
r5 = 0x80455000
r29 = 0x00001000
r30 = 0x00002000
r31 = 0x00003000
Then..
The word at Address 0x804550EC would equal 0x00001000
The word at Address 0x804550F0 would equal 0x00002000
The word at Address 0x804550F4 would equal 0x00003000
Load Multiple Word
lmw rD, SIMM (rA)
Multiple words are loaded starting at Memory Address designated by SIMM+rA. If rA = r0, then it is treated as literal 0. SIMM+rA must be divisible by 4.
The GPR used for rD *MUST* be a higher GPR that is used for rA. Therefore, it is impossible for rD to ever be r0.
The amount of words loaded is based on which GPR for rD is used.
If rD is r30, then...
Word at SIMM+rA is loaded into r30
Word at SIMM+rA+4 is laoded into r31
If rD is r25, then...
Word at SIMM+rA is loaded into r25
Word at SIMM+rA+4 is loaded into r26
Word at SIMM+rA+8 is loaded into r27
Word at SIMM+rA+12 is loaded into r28
Word at SIMM+rA+16 is loaded into r29
Word at SIMM+rA+20 is loaded into r30
Word at SIMM+rA+24 is loaded into r31
Using this instruction when rD = r31 is pointless, since a basic lwz instruction can be used instead.
lmw r29, 0x00EC (r5)
If...
r5 = 0x80442000
The word at Address 0x804420EC = 0x000A0000
The word at Address 0x804420F0 = 0x000B0000
The word at Address 0x804420F4 = 0x000C0000
Then ..
r29 would equal 0x000A0000
r30 would equal 0x000B0000
r31 would equal 0x000C0000
Store Word & Update
stwu rD, SIMM (rA)
Word value in rD is stored to Memory Address designated by SIMM+rA. If rA = r0, then it is treated as literal 0. After the word value has been stored, rA will be updated with a new value. rA's new value is calculated by SIMM+rA.
Example:
stwu r25, 0x0018 (r31)
If....
r25 = 0x1000270F
r31 = 0x80001600
Word value of 0x1000270F is stoed to Memory Address 0x80001618. Afterwards, r31 will now have the value of 0x80001618.
sthu is for halfwords, stbu is for bytes
Load Word Zero & Update
lwzu rD, SIMM (rA)
Word value located at Memory Address designated by SIMM+rA is loaded into rD. If rA = r0, then it is treated as literal 0. After the word has been loaded into rD, rA will be updated with a new value. rA's new value is calculated by SIMM+rA.
Example:
lwzu r27, 0x1000 (r4)
Load the word at address of Register 4 plus 0x1000 into Register 27. Afterwards the address of Register 4 is incremented by 0x1000
If...
r4 = 0x80EF0050
lhzu is for halfwords, lbzu is for bytes
Store String Word Immediate
stswi rD, rA, NB
A string of bytes is stored to Memory Address designated by rA. If rA = r0, then it is treated as literal zero. NB stands for Number of Bytes. It sets the byte amount for the string. It can be anything from 0 to 31. If set to 0, it is treated as 32.
The Starting Byte that will be used in the string is the far left most byte of rD. Ending Byte depends on NB. Once all bytes of a GPR are used up, but the string still has more bytes left that need to be stored, more bytes will then be used from the next higher GPR. (i.e. r7 -> r8).
If there are bytes in the string still left to be stored but GPR r31 has already been used up, then bytes of r0 will then be used.
Example:
stswi r3, r25, 12
The first 12 consecutive bytes starting from r3 going towards higher GPR's are stored to the address in r25.
If..
r3 = 0x10203040 <--First 4 out of 12 bytes
r4 = 0xFFFF0000 <--Second 4 out of 12 bytes
r5 = 0x000000028 <--Third 4 out of 12 bytes
r25 = 0x8167DE00 <--Memory Address to store string of bytes to
Then...
The entire value of 0x10203040FFFF000000000028 is stored at address 0x8167DE00.
Load String Word Immediate
lswi rD, rA, NB
A string of bytes is loaded from the Memory Address designed by rA. If rA = r0, then it is treated as literal zero. NB stands for Number of Bytes. It sets the byte amount for the string. It can be anything from 0 to 31. If set to 0, it is treated as 32.
The first byte that is loaded is loaded into the far left byte of rD. Ending byte depends on NB. Once all bytes of a GPR are used up, but the string still has more bytes left to be loaded, more bytes will then be used from the next higher GPR (i.e. r7 -> r8).
The bytes loaded cannot 'hit' rA. Therefore, because of this (and the fact NB as 0 = 32), the GPR used for rD cannot be the same GPR used for rA. If there are bytes in the string still left to be loaded, but GPR r31 has already been used up, then bytes of r0 will then be used.
The GPR used for rA *can* be higher then rD as long as NB uses a value so bytes loaded don't 'spill' back into rA itself.
Example:
lswi r3, r25, 12
The 12 bytes of data starting at the address in r25 will be loaded into the first 12 consecutive bytes starting at register 3 going towards the higher registers
If..
r25 = 0x8167DE00
And the 12 bytes starting at that address is 0x10203040FFFF000000000028
Then after the instruction is executed..
r3 = 0x10203040
r4 = 0xFFFF0000
r5 = 0x00000028
Example of an invalid use of lswi:
lswi r3, r5, 14
This is invalid because 4 bytes are loaded into r3, then 4 bytes are loaded into r4, then bytse will begin loading into r5. Thus, loaded bytes have 'spilled' back into rA. Instruction is invalid.
Here's a basic equation to know if your lswi is invalid or not
Step 1: rA minus rD (their GPR numbering values, not the values within them!)
Step 2: Multiply step 1 result by 4
Step 3: If NB is greater than Step 2 result, instruction is invalid
NOTICE that ASM Assemblers will actually allow you to compile invalid lswi instructions! You have been warned!
This reference page is for beginner ASM Coders. It covers most instructions that are suitable for beginner-level Assembly work. It does include some 'intermediate level' stuff. Therefore, if you are a Beginner and some of the stuff confuses you, you can always visit this page back later after you have gained more ASM knowledge/experience.
Advanced ASM Coders have basically no need for this page, as they should be knowledgeable enough to decipher a 'professional' level PPC-based User's Manual.
General overview:
- Instruction Name
- Syntax
- Signed vs Unsigned treatment of Values (if applicable)
- Description & Notes
- Example (if necessary)
Notes for Syntax format:
- rD = Destination General Purpose Register
- rA = Source General Purpose Register
- rB = 2nd Source General Purpose Register
- SIMM = Signed 16-bit Immediate Value Range
- UIMM = Unsigned 16-bit Immediate Value Range
- NB = Number of Bytes (for lswi and stswi only)
Load Immediate
li rD, SIMM
Loads SIMM into rD.
li r3, 0x00CC
Loads the immediate value 0x00CC into r3. r3 is now 0x000000CC.
Nop
This instruction will literally make the CPU do nothing. Nop is short for No-Operation. Some C2 Insert ASM Codes may have a nop added at the very end (by the ASM Assembler) as the source of any C2 ASM Code needs to have an odd amount of instructions.
Example:
li r0, 1
stw r0, 0 (r12)
nop
Add
add rD, rA, rB
The result of rA + rB is placed into rD.
add r6, r5, r4
If..
r5 = 4
r4 = 5
Then r6 would equal 0x00000009
Subtract
sub rD, rA, rB
The result of rA - rB is placed into rD.
sub r12, r11, r4
If..
r11 = 0
r4 = 4
Then r12 would equal -4 (0xFFFFFFFC)
Add Immediate
addi rD, rA, SIMM
The result of rA + SIMM is placed into rD. If rA = r0, then rA is treated as literal 0.
addi r6, r5, 2
If..
r5 = 4
Then r6 would equal 0x00000006
Subtract Immediate
subi rD, rA, SIMM
The result of rA - SIMM is placed into rD. If rA = r0, then rA is treated as literal 0.
subi r30, r16, 1
If..
r16 = 1
Then r30 would equal zero.
Load Immediate Shifted
lis rD, UIMM
Loads UIMM into the upper 16 bits of rD. Lower 16 bits of rD are cleared (zeroed)
lis r12, 1
Loads the immediate value of 1 into the upper 16 bits of r12, lower 16 bits are cleared. r12 is now 0x00010000
Or Immediate
ori rD, rA, UIMM
For most uses in Assembly Codes, ori is used along with lis to write a complete word value to a register.
Example:
lis r4, 0x8000
ori r4, r4, 0x15EC
r4 is now 0x800015EC
Add Immediate Shifted
addis rD, rA, UIMM
UIMM (as VVVV0000) is added to rA. The result is placed into rD. Therefore, the lower bits of rA will always be 'copied' over to rD in any addis instruction. If rA = r0, then rA is treated as literal 0.
addis r6, r5, 2
If..
r5 = 4
Then r6 would equal 0x00020004.
Subtract Immediate Shifted
subis rD, rA, SIMM
The result of rA minus SIMM (as VVVV0000) is placed into rD. Therefore, the lower bits of rA will always be 'copied' over to rD in any subis instruction. If rA = r0, then rA is treated as literal 0.
subis r11, r7, 0x2000
If..
r7 = 0x10005555
Then r11 would equal 0xF0005555.
Store Word
stw rD, SIMM (rA)
Word value in rD is stored to the memory address designated by SIMM+rA. If rA = r0, then rA is treated as literal 0.
stw r3, 0x0002 (r4)
If..
r3 = 0x00000005
r4 = 0x80001574
Then the word at Memory Address 0x80001576 is now 0x00000005.
Store Halfword
sth rD, SIMM (rA)
Halfword value in rD is stored to the memory address designated by SIMM+rA. If rA = r0, then rA is treated as literal 0.
sth r3, 0x0002 (r4)
If..
r3 = 0x00000005
r4 - 0x80001574
Then the halfword at Memory Address 0x80001576 is now 0x0005.
Store Byte
stb rD, SIMM (rA)
Byte value in rD is stored to the memory address designed by SIMM+rA. If rA = r0, then rA is treated as literal 0.
stb r3, 0x0002 (r4)
If..
r3 = 0x00000005
r4 = 0x80001574
Then the byte at Memory Address 0x80001576 is now 0x05.
Load Word & Zero
lwz rD, SIMM (rA)
The word value in Memory located at SIMM+rA is loaded into rD. If rA = r0, then rA is treated as literal 0.
lwz r3, 0x0002 (r4)
If...
r4 = 0x80001574
& Word value at Memory Address 0x80001576 is 0x1500FFFF
Then r3 would equal 0x1500FFFF.
Load Halfword & Zero
lhz rD, SIMM (rA)
The halfword value in Memory located at SIMM+rA is loaded into rD. Upper 16 bits of rD are cleared (zeroed). If rA = r0, then rA is treated as literal 0.
lhz r3, 0x0002 (r4)
If..
r4 = 0x80001574
& Halfword value at Memory Address 0x80001576 is 0x1500
Then r3 would equal 0x00001500.
Load Byte & Zero
lbz rD, SIMM (rA)
The byte value in Memory located at SIMM+rA is loaded in rD. The left-hand side 3 bytes of rD are cleared (zeroed). If rA = r0, then rA is treated as literal 0.
lbz r3, 0x0002 (r4)
If..
r4 = 0x80001574
& Byte value at Memory Address 0x80001576 = 0x15
Then r3 would equal 0x00000015.
Move Register
mr rD, rA
Value of rA is copied to rD.
mr r4, r3
If..
r3 = 0xFFFFFFD0
Then r4 = 0xFFFFFFD0.
Multiply Low Word Signed
mullw rD, rA, rB
Signed
The result of rA x rB is placed into rD. The multiplication is Signed. If the result exceeded a 32-bit sized value, then only the lower 32 bits of said value are used as the result in rD.
mullw r9, r3, r0
If...
r0 = 0x00000005
r3 = 0x0000000B
Then r9 would equal 0x00000037
Multiply Immediate Signed
mulli rD, rA, SIMM
Signed
Thre result of rA x rB is placed into rD. The multiplication is Signed. If the result exceeded a 32-bit sized value, then only the lower 32 bits of said value are used as the result in rD>
mulli r10, r10, 0x0004
If..
r10 = 0x0000000C
Then r10 would equal 0x00000030
Divide Word Signed
divw rD, rA, rB
Signed
The result of rA / rB is placed into rD. The division is Signed. If rounding is needed, the number will round *DOWN* to the closest whole number. Let's pretend you executed a divw instruction that had a result of 1.9 (0x1.E66~ in Hex), the result placed into rD will be 1.
divw r4, r30, r15
If..
r30 = 0xFFFFFFFC
r15 = 0x00000002
Then r4 would equal 0xFFFFFFFE.
Divide Word Unsigned/Logical
divwu rD, rA, rB
Unsigned/Logical
The result of rA / rB is placed in rD. The division is Unsigned and thus, all values are treated as positive. If rounding is needed, the number will round *DOWN* to the closest whole number.
divwu r4, r30, r15
If..
r30 = 0xFFFFFFFC
r15 = 0x00000002
Then r4 would equal 0x7FFFFFFE.
Branch
b SIMM
The execution of the CPU will jump forward/backward based on the amount designated in SIMM. SIMM must be divisible by 4. If SIMM is positive then the CPU jumps 'down', visually speaking. If SIMM is negative, then the CPU jumps 'back up'. If SIMM is zero, the CPU simply halts.
For Assembly Codes, branch labels (SIMM is replaced with a custom name) are used instead of writing out the Signed 16-bit Immediate Value (SIMM).
Example:
b the_label
li r5, 0
the_label:
stb r5, 0 (r12)
The instruction where the Brancj jump lands at is also present but needs to have a colon appended. The 'li r5, 0' instruction is skipped because the branch above to jumping to 'the_label' which is pointing to the stb instruction.
Branch If Equal
beq SIMM
If the previous comparison instruction had a condition where the result was equal, then the branch will be taken. Branch labels (custom names) are used in place of SIMM.
Example code showing use of beq instruction
cmpwi r5, 3
beq some_label
li r0, 9
some_label:
stw r0, 0 (r12)
beq is part of a large family of Conditional Branch Instructions.
List of other commonly used Conditional Branches~
bgt = Branch If Greater Than
blt = Branch If Less Than
ble = Branch If Less Than Or Equal
bge = Branch If Greater Than Or Equal
Compare Word Immediate Signed
cmpwi rD, SIMM
Signed
Value in rD is compared to SIMM. The comparison is Signed. A conditional branch should be placed afterwards to branch based on the result of the comparison.
Compare Word Signed
cmpw rD, rA
Signed
Value in rD is compared to value in rA. The comparison is Signed. A conditional branch should be placed afterwards to branch based on the result of the comparison.
Compare Logical Word Immediate Unsigned/Logical
cmplwi rD, UIMM
Logical
Value in rD is compared to UIMM, the comparison is unsigned. All values are treated as unsigned. A conditional branch should be placed afterwards to branch based on the result of the comparison.
Compare Logical Word Unsigned/Logical
cmplw rD, rA
Logical
Value in rD is compared to value in rA, the comparison is unsigned. All values are treated as unsigned. A conditional branch should be placed afterwards to branch based on the result of the comparison.
Store Word Indexed
stwx rD, rA, rB
The word value of rD is stored to the Memory Address designated by rA + rB. If rA = r0, then it is treated as literal zero.
stwx r12, r12, r29
If...
r12 = 0x00000200
r29 = 0x80001000
Then the word at Memory Address 0x80001200 is now 0x00000200.
sthx is for halfwords, stbx is for bytes
Load Word & Zero Indexed
lwzx rD, rA, rB
The word value located at the Memory Address designated by rA + rB is loaded into rD. If rA = r0, then it is treated as literal zero.
lwzx r30, r4, r16
If...
r4 = 0x00000008
r16 = 0x80005000
& word value at Memory Address 0x80005008 is 0x000000FF
Then r30 would equal 0x000000FF.
lhzx is for halfwords, lbzx is for bytes
Move to Count Register
mtctr rD
The value in rD is copied to the Count Register (CTR).
Move from the Count Register
mfctr rD
The value in the Count Register (CTR) is copied to rD
Branch Decrement When Not Zero
bdnz SIMM
The count register is subtracted by 1 (aka decremented), then the count register is compared to the value of 0. If the count register is not zero, the branch is taken. For assembly codes, the use of label names replace SIMM. SIMM must be divisible by 4, this is not a concern for Coders if they stick to using branch label names.
This instruction is used to make loops (along with the mtctr instruction).
Move To Link Register
mtlr rD
The value rD is copied to the Link Register (LR).
Move From Link Register
mflr rD
The value in the Link Register (LR) is copied to Register rD
Branch & Link
bl SIMM
An unconditional branch is executed, the amount the branch 'jumps' is based on SIMM. SIMM must be divisible by 4. This won't be an issue for you if you use branch labels. After the branch has been executed, the address of the branch instruction+4 is written to the Link Register.
This instruction is used mainly for creating subroutines in your code.
Example showing mem addresses and instructions~
80456124 : bl 0x1F8C
80456128 : cmpwi r3, 0
8045612C : add r5, r3, r4
Once the 'bl 0x1F8C' instruction has executed, the Link Register will now contain 80456128.
Branch to Link Register
blr
Execution of the CPU will branch/jump to the Memory Address that's in the Link Register.
Branch to Count Register
bctr
Execution of the CPU will branch/jump to the Memory Address that's in the Count Register.
Store Multiple Word
stmw rD, SIMM (rA)
Multiple words are stored starting at Memory Address designated by SIMM+rA. If rA = r0, then it is treated at literal 0. SIMM+rA must be divisible by 4.
The amount of words stored is based on which GPR for rD is used.
If rD is r30, then...
r30's word value is stored to SIMM+rA
r31's word value is stored to SIMM+rA+4
If rD is 25, then...
r25's word value is stored to SIMM+rA
r26's word value is stored to SIMM+rA+4
r27's word value is stored to SIMM+rA+8
r28's word value is stored to SIMM+rA+12
r29's word value is stored to SIMM+rA+16
r30's word value is stored to SIMM+rA+20
r31's word value is stored to SIMM+rA+24
Using this instruction when rD = r31 is pointless, since a basic stw instruction can be used instead.
Example:
stmw r29, 0x00EC (r5)
If..
r5 = 0x80455000
r29 = 0x00001000
r30 = 0x00002000
r31 = 0x00003000
Then..
The word at Address 0x804550EC would equal 0x00001000
The word at Address 0x804550F0 would equal 0x00002000
The word at Address 0x804550F4 would equal 0x00003000
Load Multiple Word
lmw rD, SIMM (rA)
Multiple words are loaded starting at Memory Address designated by SIMM+rA. If rA = r0, then it is treated as literal 0. SIMM+rA must be divisible by 4.
The GPR used for rD *MUST* be a higher GPR that is used for rA. Therefore, it is impossible for rD to ever be r0.
The amount of words loaded is based on which GPR for rD is used.
If rD is r30, then...
Word at SIMM+rA is loaded into r30
Word at SIMM+rA+4 is laoded into r31
If rD is r25, then...
Word at SIMM+rA is loaded into r25
Word at SIMM+rA+4 is loaded into r26
Word at SIMM+rA+8 is loaded into r27
Word at SIMM+rA+12 is loaded into r28
Word at SIMM+rA+16 is loaded into r29
Word at SIMM+rA+20 is loaded into r30
Word at SIMM+rA+24 is loaded into r31
Using this instruction when rD = r31 is pointless, since a basic lwz instruction can be used instead.
lmw r29, 0x00EC (r5)
If...
r5 = 0x80442000
The word at Address 0x804420EC = 0x000A0000
The word at Address 0x804420F0 = 0x000B0000
The word at Address 0x804420F4 = 0x000C0000
Then ..
r29 would equal 0x000A0000
r30 would equal 0x000B0000
r31 would equal 0x000C0000
Store Word & Update
stwu rD, SIMM (rA)
Word value in rD is stored to Memory Address designated by SIMM+rA. If rA = r0, then it is treated as literal 0. After the word value has been stored, rA will be updated with a new value. rA's new value is calculated by SIMM+rA.
Example:
stwu r25, 0x0018 (r31)
If....
r25 = 0x1000270F
r31 = 0x80001600
Word value of 0x1000270F is stoed to Memory Address 0x80001618. Afterwards, r31 will now have the value of 0x80001618.
sthu is for halfwords, stbu is for bytes
Load Word Zero & Update
lwzu rD, SIMM (rA)
Word value located at Memory Address designated by SIMM+rA is loaded into rD. If rA = r0, then it is treated as literal 0. After the word has been loaded into rD, rA will be updated with a new value. rA's new value is calculated by SIMM+rA.
Example:
lwzu r27, 0x1000 (r4)
Load the word at address of Register 4 plus 0x1000 into Register 27. Afterwards the address of Register 4 is incremented by 0x1000
If...
r4 = 0x80EF0050
lhzu is for halfwords, lbzu is for bytes
Store String Word Immediate
stswi rD, rA, NB
A string of bytes is stored to Memory Address designated by rA. If rA = r0, then it is treated as literal zero. NB stands for Number of Bytes. It sets the byte amount for the string. It can be anything from 0 to 31. If set to 0, it is treated as 32.
The Starting Byte that will be used in the string is the far left most byte of rD. Ending Byte depends on NB. Once all bytes of a GPR are used up, but the string still has more bytes left that need to be stored, more bytes will then be used from the next higher GPR. (i.e. r7 -> r8).
If there are bytes in the string still left to be stored but GPR r31 has already been used up, then bytes of r0 will then be used.
Example:
stswi r3, r25, 12
The first 12 consecutive bytes starting from r3 going towards higher GPR's are stored to the address in r25.
If..
r3 = 0x10203040 <--First 4 out of 12 bytes
r4 = 0xFFFF0000 <--Second 4 out of 12 bytes
r5 = 0x000000028 <--Third 4 out of 12 bytes
r25 = 0x8167DE00 <--Memory Address to store string of bytes to
Then...
The entire value of 0x10203040FFFF000000000028 is stored at address 0x8167DE00.
Load String Word Immediate
lswi rD, rA, NB
A string of bytes is loaded from the Memory Address designed by rA. If rA = r0, then it is treated as literal zero. NB stands for Number of Bytes. It sets the byte amount for the string. It can be anything from 0 to 31. If set to 0, it is treated as 32.
The first byte that is loaded is loaded into the far left byte of rD. Ending byte depends on NB. Once all bytes of a GPR are used up, but the string still has more bytes left to be loaded, more bytes will then be used from the next higher GPR (i.e. r7 -> r8).
The bytes loaded cannot 'hit' rA. Therefore, because of this (and the fact NB as 0 = 32), the GPR used for rD cannot be the same GPR used for rA. If there are bytes in the string still left to be loaded, but GPR r31 has already been used up, then bytes of r0 will then be used.
The GPR used for rA *can* be higher then rD as long as NB uses a value so bytes loaded don't 'spill' back into rA itself.
Example:
lswi r3, r25, 12
The 12 bytes of data starting at the address in r25 will be loaded into the first 12 consecutive bytes starting at register 3 going towards the higher registers
If..
r25 = 0x8167DE00
And the 12 bytes starting at that address is 0x10203040FFFF000000000028
Then after the instruction is executed..
r3 = 0x10203040
r4 = 0xFFFF0000
r5 = 0x00000028
Example of an invalid use of lswi:
lswi r3, r5, 14
This is invalid because 4 bytes are loaded into r3, then 4 bytes are loaded into r4, then bytse will begin loading into r5. Thus, loaded bytes have 'spilled' back into rA. Instruction is invalid.
Here's a basic equation to know if your lswi is invalid or not
Step 1: rA minus rD (their GPR numbering values, not the values within them!)
Step 2: Multiply step 1 result by 4
Step 3: If NB is greater than Step 2 result, instruction is invalid
NOTICE that ASM Assemblers will actually allow you to compile invalid lswi instructions! You have been warned!