|
|
|
I tend to port and program video game console emulators to the iPhone and iPod Touch series of devices. Therefore, I deal with ARM assembly language a lot. One of the issues I ran into was the use of a particular register, R9.
Many CPU emulation cores are handwritten in tight assembly. Every register is used as effectively as humanly possible. So when you find out that writing to R9 then exiting that function tends to cause crashing galore, you’re not pleased. It seems (and correct me if I’m wrong) this is due to the iPhone & iPod Touch’s operating system’s use of Thread Local Storage, also known as TLS. I needed to use R9 to realistically deliver emulators which use such tightly written assembly. After speaking with the very knowledgeable Exophase, creator of software such as gpSP, I was soon presented with a solution.
The solution focuses on saving and restoring R9 within the assembly code by wrapping calls of functions outside this code. Here’s how this process will go:
To simplify this example let’s say you have a chunk of memory allocated with its address stored in a register defined as reg_cpu_var. You have space for two 32bit values within this buffer which will contain contents of R9. The offset of these values in the buffer are (poorly) defined as iphone_r9_ofs and iphone_r9s_ofs.
You want to save the contents of R9 before it is accessed in a place such as the entrance of the assembly function:
str r9, [reg_cpu_var, #iphone_r9s_ofs]
Once the contents of R9 are stored in memory, you can continue to run your assembly code until you get to a function call outside of your assembly code. At that point you want to save and restore R9 by wrapping the function call as follows:
str r9, [reg_cpu_var, #iphone_r9_ofs]
ldr r9, [reg_cpu_var, #iphone_r9s_ofs]@ Call the function saving and restoring like normal.
ldr r9, [reg_cpu_var,#iphone_r9_ofs]
Although I have not needed to do so, depending on the nature of your program you may need to restore R9 on exit of the assembly function where you originally saved R9. If this is the case you can do this like so:
ldr r9, [reg_cpu_var, #iphone_r9s_ofs]
By doing the above, you will be able to use ARM assembly which requires R9. This has allowed me to expand my emulator work by improving performance with the introduction to assembly cores, as well as adding a new usable register to dynamic recompilers.
For many this may be a bit technical, but for that rare breed of developer on these Apple platforms, I hope this has been helpful.
Thanks,
ZodTTD