GP32 Is it possible to optimize this example ?


ConsoleTom

Member
Joined
Dec 4, 2003
Messages
106
Age
47
Location
Germany
Website
Visit site
Hi !

I am trying to optimize an Emu and i would like to rewrite routines in assembly. Now i would like to know if it would be an optimization when i rewrite this example in assembly ?

There are many if's and switch+case and i thought when i rewrite all (i know it's a lot of work but i really have time) it should get faster. Am i right or is it nonsensical ?

...
switch(addr&0xff)
{
case (TIM6BKUP&0xff):
mTIM_6_BKUP=data;
break;

case (TIM7BKUP&0xff):
mTIM_7_BKUP=data;
break;

case (TIM0CTLA&0xff):
mTimerInterruptMask&=(0x01^0xff);
mTimerInterruptMask|=(data&0x80)?0x01:0x00;
mTIM_0_ENABLE_RELOAD=data&0x10;
mTIM_0_ENABLE_COUNT=data&0x08;
mTIM_0_LINKING=data&0x07;
if(data&0x40) mTIM_0_TIMER_DONE=0;
if(data&0x48)
{
mTIM_0_LAST_COUNT=gSystemCycleCount;
gNextTimerEvent=gSystemCycleCount;
}
break;
...


My ASM-Code of one 'case' could look like this

<save used registers>
ldr r0, =addr
ldr r1, =TIM7BKUP
and r0,r0,#0xFF
and r1,r1,#0xFF
cmp r0,r1
bne othercase

ldr r0,=mTIM_7_BKUP
ldr r1,=data
str r0,[r1]

othercase:
...
<load used registers and exit>

Is this code ok like this ? Could it be done better ? And is it faster then c ?

Greetings

Tobias
 
dont know what the compiler would do with the c-code but maybe i got an optimization of your asm code.
would it be possible to use "LDRB" instead of "LDR"? so you dont need the "and r0,r0,#0xFF", because LDRB loads only the first byte of the var.

P.S.: i just started to learn arm asm so i'm not realy sure ;)
(but i'm quite experienced with optimizing x86-asm-code B) )
 
Hi !

Sure. LDRB is better - i thought already about this solution. So when the datatype is char/byte i'll use LDRB.

Greetings

Tobias
 
Hi

I'm new to ARM ASM myself but if there was going to be a case for all 256 possible combinations of a byte then it might be best to build a jump table.


ldrb r1,[r0]

add pc,pc,r1,lsl #2
mov r0,r0 (Just padding)
b CASE00
b CASE01
b CASE02
etc

CASE00:
....
.....
b ENDOFCASE

CASE01:
.....
....
b ENDOFCASE

ENDOFCASE:

It saves doing all the CMPs and is hopefully a bit faster.

By the way, it looks as if the registers are the wrong way around in you str instruction.

Dave
 
Hi ConsoleTom

Optimization is a multiple stage process but usually consists of the following:

1) Profiling code
To factually find out which chunk of code is taking up the most time, and thus enabling you to decide which pieces/levels to attack first. This quite often is were coders go wrong, and the usual happy coder thing to do is say "ahh yes it's this bit of code thats slow" - without actually checking it. Usually writing your own profile tools is enough to do the job. All the stuff that I wrote on the GP32 used a simple marcro PROFILE

Profile("MainLoop",
MainLoop();
)

all the profile macro did was to effectivly create a very simple

ProfileStart("MainLoop");
MainLoop();
ProfileStop();

structure around the code to be test. it was then a case of drilling down into the various levels below that to find out what eats up the cpu time per frame. You can reprogram the gp32 audio buffering to get a much higher timer resolution than the standard gettickcount();

2) Logical optimization
At this point you should have found out the bottle necks in your code. What should be done now is high level optimization - is there a better/faster/smaller/simpler way of doing the same job. In some cases it's often better to jump a level above the code that you're working on to get a global view of how it all works and start planning new directions from there. In your case a simple optimization would be maybe try using a function point table (jump table), or even doing some stats on the most used cases and putting them outside that main loop. This stage *never* involves uses asm or any low level coding. Usually the biggest speed gains are developed here - by simply understanding the current code.

3) Pure code optimization
This is the most boring stage usually. it just means trawling thro the code looking for potential optimizations that the compiler will have missed or has no idea about. This can involve converting to asm - but in most cases it's really only the lowest level inner loops that'll ever need asm or benefit from using it. A big killer in this case is "coders speculation" - were a coder will never try an idea because they're sure it wont make any difference. It really is worth trying every idea you have - I'm sure you'll be surprised by some stuff :) CPUS,Caches and Memory systems are now quite complicated, such that determining code speed is a black art in itself.

A totally common mistake is to jump in and convert everything to asm - this is a terrible idea, it can means that potentially you'll just slightly speed up bad logic code. For e.g. in the case of neopop - if you converted that to asm - it really wouldn't speed it up much, becuase there's a bug/inefficency in the way it syncros the cpu and interrupts - that'll cause to be slow no matter how much you speed up the low level routines.

Anyhow just a few ideas that have helped me in my gp32 stuff. Have fun...
 
Back
Top