ASM & Register Safety
Once your ASM code creating skills have gone beyond 'super basic', you will eventually run into a situation where you will need to manipulate other registers than just the ones that by the default instruction at your code's address.
Let's discuss Register Safety
Once your ASM code creating skills have gone beyond 'super basic', you will eventually run into a situation where you will need to manipulate other registers than just the ones that by the default instruction at your code's address.
Let's discuss Register Safety
A code creator simply cannot choose at will which registers to use as a temporary space to read and/or write data. Doing so can cause unwanted effects on the game. Even if a code appears to be working, you may be effecting 'hidden' functions of the game in a seriously detrimental manner.
Let's go over all the General Purpose Registers and explain which ones you are allowed to use...
Register 12 (99.9% Safe)
Register 12 is the safest register. 99.9% of the time, you can use this register freely. Freely meaning you do not have to restore it's original contents at any point in your source.
Register 11 (99% Safe)
Register 11 is what I call r12's little brother in regards to safety. 99% of the time, you can use this register freely.
Register 0, and Registers 3 thru 10 (Semi Safe)
r0, and r3 thru r10 are what is known as volatile registers.
You can sometimes use these registers freely w/o restoring their original values. But this is not wise. If you must use these registers, please restore their original value(s).
Even with that being said, restoring the original value(s) is NOT a 100% guarantee for register safety.. Let's say you have a code, and you notice that r7 is usually the value of 0 whenever the default instruction at the code's address is executed. So at the end of you code, you write li r7, 0. Good, right? Maybe not. There could be a chance that r7 can be something other than 0. I'd advise testing a breakpoint multiple times (in varying circumstances of the game) to be sure a certain volatile register always holds a specific value.
Generally speaking with the volatile registers, the higher the number, the safer it is. So r10 would be the most 'safest' to use, with r3 being the least safe. r0 plus r3 and r4 are generally less safe than r5 thru r10.
If you must use one of these registers and want to save compiled code length by not restoring their original value(s), then stick with r10. I would give r10 a 95% 'safety rating' for use without restoring its value.
In conclusion, If you have to use the volatile registers, don't use r0, r3, and r4. Restore values for r5 thru r10. However, you don't have to restore r10 and will most likely be OK.
Registers 14 thru 31 (Not Safe)
r14 thru r31 are non-volatile registers. They are called the Global Variable Registers (or just GVR's). Their values must always be preserved.
Registers 1, 2, & 13 (Dangerous)
Never, and I repeat NEVER use r1, r2, and r13!! Even if you backup their values and restore them, this is still dangerous. These registers are used by the CPU to access specific areas of memory related to constants, global variables, etc. They will be read during interrupts which you will not see or know about. For specific circumstances, r1 can be used with its original value backed up (called pushing/popping the stack), which will be covered in the next segment.
Fyi: r1 is also called sp (stack pointer), and r2 is also called rtoc (register table of contents).
At this point, you are probably wondering what is an efficient way to get more free registers. Before we dive into that, let's discuss a quick easy trick to get some free registers.
Looking Ahead Beyond your Code Address...
We know we can always use r11, and r12. Let's say the address after your code's address has this instruction - mulli r31, r8, 0x4
You can actually use r31 freely. This is because once your code is completely finished and the next address's instruction is executed by the game, r31 is going to be written to regardless. Obviously, this also shows that we cannot mess with r8 freely as r8 is being used as a source register of the mulli instruction to determine the result to write to r31.
Now you know that handy trick to get some more free registers, here's a rock solid method that allows you to use r14 thru r31.
This method is called the 'Push/Pop the Stack' method.
Code:
#Default instruction could reside here...
stwu sp, -0x0050 (sp) #make space for 18 registers
stmw r14, 0x8 (sp) #push r14-r31 onto the stack pointer
#Your ASM contents go here
lmw r14, 0x8 (sp) #pop r14-r31 off the stack pointer
addi sp, sp, 0x0050 #release the space
#Default instruction could reside here...
The stwu, stmw instructions will make space for a new stack frame and set a new stack pointer, then the registers' values are stored onto the stack pointer. The lmw, addi instructions will restore all the registers' values, release the stack space, and recover the original stack pointer value. Thus the instructions are not violating any safety protocols. As a beginner ASM coder, you don't need to worry about the finer technical details of how this works. Once you become an advanced coder who needs to create custom stack frames, then the technical details will matter.
You can now use r14 thru r31. If you include r11 and r12, you will have 20 free registers to use!
Question: Are there any cons to using the Push/Pop Stack method?
Generally, no. If you are nit picky about shortening the length of compiled code as much as possible, then try not to use it. As the method consists of four total ASM instructions.
There is a very very rare chance that this can cause a crash. I would rate it a 99.99% 'success' rate.
Quick info about Floating Point Registers:
f9 thru f13 (99% safe; same level of safety as r11/r12; the higher the number, the more safe)
f2 thru f8 (Semi safe; same level of safety as r5 thru r10; the higher the number, the more safe)
f0 & f1 (Semi safe; same level of safety as r0, r3, r4)
f14 thru f31 (NOT safe; values must be preserved)
Beginner/Intermediate Coders will never need to 'push/pop' the stack for FPRs. So technical details of doing that will not be covered in this thread
Quick info about Condition Fields:
For Advanced ASM Coders only.
For Advanced ASM Coders only.
cr5 thru cr7 (99% safe; same level of safety as r11/r12)
cr0 & cr1 (Semi safe; same level of safety as r0, r3, r4)
cr2 thru cr4 (NOT safe; values must be preserved)
Conclusion:
Proper register safety is a must for any code. It is dependent on the responsibility of the coder to do his/her research and have their code(s) be safe for use in the game.
All Credits to:
dcx2
Y.S.