gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

ASM > ASM to C

#160066 - naleksiev - Thu Jul 10, 2008 12:40 am

I was profiling something at work and I notice that switch case always have the default case at the top. The first two instructions in the fake example below.

Code:
cmp         r4,#3
bhi         *+56           
add         pc,pc,r4,lsl #2
nop         
b           *+16           
b           *+20           
b           *+24           
b           *+28           
mov         lr,#2
b           *+24
mov         lr,#3
b           *+16
mov         lr,#4
b           *+8
mov         lr,#5


This case should never happened in my code. If I was writing it in ASM it should be fine to get rid of the cmp and bhi. The problem is that it won't wort the optimization compared to code readability.

So is it possible this to be done in C / C++?

#160077 - sgeos - Thu Jul 10, 2008 4:16 am

The ASM code produced by a C or C++ code segment (or anything else for that matter) is highly dependant on the compiler you use. Exact behavior will vary across make, version, and optimization level of the compiler.

The question is, do you need this code to be more efficient? Most of the time, the answer is no. If the answer is yes, either find a better algorithm or rewrite your current algorithm in hand optimized assembler.

-Brendan

#160121 - naleksiev - Thu Jul 10, 2008 5:22 pm

sgeos wrote:
The question is, do you need this code to be more efficient?


To save 2 cycles... it's fine the way it is. I was just wandering if I can trick the compiler that I don't have default case and that the variable in the switch will have one of the listed values.

#160124 - sajiimori - Thu Jul 10, 2008 5:52 pm

On GCC, you can do this, but it's not exactly the same (because it involves an LDR):
Code:
int test(int n)
{
   static const void* labels[] =
   {
      &&L1,
      &&L2,
      &&L3,
   };

   goto *labels[n];

L1:
   return 123;
L2:
   return 456;
L3:
   return 789;
}

#160129 - sgeos - Thu Jul 10, 2008 7:11 pm

naleksiev wrote:
To save 2 cycles... it's fine the way it is.

If you are calling it 2000 times a frame, 2 cycles becomes 4000 and that may be a big deal.

naleksiev wrote:
I was just wandering if I can trick the compiler that I don't have default case and that the variable in the switch will have one of the listed values.

Your current compiler? Maybe. All compilers? No. What works for one makes things less efficient for another. In general, just write simple code and worry about cycles when you need to.

sajiimori wrote:
On GCC, you can do this, but it's not exactly the same (because it involves an LDR):
Code:
int test(int n)
{
   static const void* labels[] =
   {
      &&L1,
      &&L2,
      &&L3,
   };

   goto *labels[n];

L1:
   return 123;
L2:
   return 456;
L3:
   return 789;
}

I've never seen voodoo like that before.
Then again, I can't say there are many goto gurus out there.

-Brendan

#160143 - Miked0801 - Thu Jul 10, 2008 9:41 pm

It's a hand coded jump table. God knows what crap the compiler will do to it though :)

You could always not define one of your cases and let it go to default - let it be the most actively called function. Of course, I do not at all recommend that kind of code for anything outside of very special case routines that you will be married to for all eternity.

#160149 - naleksiev - Thu Jul 10, 2008 10:29 pm

Thank you guys!

The jump table makes sense although I'm going to add it to my code :):):) But that was the answer to my question.

#160158 - Dwedit - Thu Jul 10, 2008 11:23 pm

Jump tables aren't standard C. The "Cil" compiler turns a GCC style jump table into a switch block before compiling.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."