GCC-SH4 tips: Difference between revisions
No edit summary |
(Markdown => WikiText) |
||
Line 1: | Line 1: | ||
These notes is mostly taken from the good advice of all the Dreamcast scholars (Ian Micheal, Moop, MrNeo, and more). | These notes is mostly taken from the good advice of all the Dreamcast scholars (Ian Micheal, Moop, MrNeo, and more). | ||
The original documents can be found [here.](https://dreamcast.wiki/wiki/images/f/f6/Gcc_asm_sh4_tips.txt) | The original documents can be found [here.](https://dreamcast.wiki/wiki/images/f/f6/Gcc_asm_sh4_tips.txt) | ||
==Dan Potter's GCC-SH4 tips== | |||
===Use local variables=== | |||
Global variables are slow - to retrieve the value, the SH4 typically must execute: | Global variables are slow - to retrieve the value, the SH4 typically must execute: | ||
<code>mov.l L2,r1</code> | |||
<code>mov.l @r1,r1</code> | |||
Local variables are faster - it's stack-relative, and **function parameters are even faster because the first four integers parameters are passed in r4-r7 and first eight floating-point parameters in fr4-fr11**. | Local variables are faster - it's stack-relative, and **function parameters are even faster because the first four integers parameters are passed in r4-r7 and first eight floating-point parameters in fr4-fr11**. | ||
===Write small functions=== | |||
We've noticed GCC generates very pessimal code when it starts to spill registers, so try to avoid doing too much in one function. | We've noticed GCC generates very pessimal code when it starts to spill registers, so try to avoid doing too much in one function. | ||
Line 20: | Line 20: | ||
A function which exceeds more than about a hundred lines should be broken into smaller functions. | A function which exceeds more than about a hundred lines should be broken into smaller functions. | ||
===Use struct copies (instead of copying individual elements of a struct)=== | |||
GCC and G++ generate code with weak scheduling when copying a struct by individual elements. | GCC and G++ generate code with weak scheduling when copying a struct by individual elements. | ||
GCC and G++ generate code with better instruction scheduling when copying a struct via struct assignment. | GCC and G++ generate code with better instruction scheduling when copying a struct via struct assignment. | ||
== Division == | |||
Using division on the Dreamcast is very costly. | Using division on the Dreamcast is very costly. | ||
=== Integer === | |||
If you're using integer and want to divide by a power of two, you're better off using bit shifting. | If you're using integer and want to divide by a power of two, you're better off using bit shifting. | ||
<code>int result = var1 >> 1; //is the same as var1 / 2 but way faster</code> | |||
<code>int result = var1 >> 2; // = var1 / 4</code> | |||
<code>int result = var1 >> 3; // = var1 / 8</code> | |||
=== Float === | |||
If you're using float, transforming your division into a multiplication is also faster. Multiplying takes 3 cycles while division takes around 13 cycles.<ref>''[http://www.shared-ptr.com/sh_insns.html]'', SH4 Assembly Instructions</ref> | |||
<code>float result = var1 * 0.5; // same as / 2 but way faster</code> | |||
<code>float result = var1 * 0.25; // same as / 4 but way faster</code> | |||
<code>float result = var1 * 0.1; // same as / 10 but way faster</code> | |||
==References== | ==References== | ||
<references/> | <references/> |
Revision as of 19:05, 24 January 2020
These notes is mostly taken from the good advice of all the Dreamcast scholars (Ian Micheal, Moop, MrNeo, and more). The original documents can be found [here.](https://dreamcast.wiki/wiki/images/f/f6/Gcc_asm_sh4_tips.txt)
Dan Potter's GCC-SH4 tips
Use local variables
Global variables are slow - to retrieve the value, the SH4 typically must execute:
mov.l L2,r1
mov.l @r1,r1
Local variables are faster - it's stack-relative, and **function parameters are even faster because the first four integers parameters are passed in r4-r7 and first eight floating-point parameters in fr4-fr11**.
Write small functions
We've noticed GCC generates very pessimal code when it starts to spill registers, so try to avoid doing too much in one function.
A function which exceeds more than about a hundred lines should be broken into smaller functions.
Use struct copies (instead of copying individual elements of a struct)
GCC and G++ generate code with weak scheduling when copying a struct by individual elements. GCC and G++ generate code with better instruction scheduling when copying a struct via struct assignment.
Division
Using division on the Dreamcast is very costly.
Integer
If you're using integer and want to divide by a power of two, you're better off using bit shifting.
int result = var1 >> 1; //is the same as var1 / 2 but way faster
int result = var1 >> 2; // = var1 / 4
int result = var1 >> 3; // = var1 / 8
Float
If you're using float, transforming your division into a multiplication is also faster. Multiplying takes 3 cycles while division takes around 13 cycles.[1]
float result = var1 * 0.5; // same as / 2 but way faster
float result = var1 * 0.25; // same as / 4 but way faster
float result = var1 * 0.1; // same as / 10 but way faster