It is currently Thu Sep 19, 2019 4:25 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: Mon Nov 12, 2007 5:55 pm 
Offline

Joined: Fri Nov 09, 2007 10:38 am
Posts: 16
Hello again!

I am currently writing the opcode handling routine, and I fear the routine is going to blow up into a massive switch-case-web. So, in the light of optimizing, is it worth rewriting the part that I have (approximately 40 opcodes) into a different format?

I am thinking of replacing the case-statements with a label prefix and executing a (computer science course teachers, please beware) goto at the beginning of the handling routine. I understand that this will introduce an additional jump-instruction at the start of each opcode, but it removes the need of comparing the fetched byte to each and every opcode. Additionally, this will make sure that the opcodes at the end of the list start almost as fast as those at the beginning. Ofcourse one could use a list of opcode stastistics (I swear I have seen one, I forgot where) to determine opcode placement in the switch-statement.

Can anybody shed some light on this issue? My arguments seem to favor the goto-approach, but I'd like to know if I'm forgetting something before making an important design decision like this one.


Last edited by johnnie on Mon Nov 12, 2007 6:32 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Dynamic goto label?
PostPosted: Mon Nov 12, 2007 6:15 pm 
Offline

Joined: Fri Nov 09, 2007 10:38 am
Posts: 16
Hm.. Come to think of it: Is it at all possible to use a dynamic goto label like LBL_(OPCODE) in C?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 12, 2007 7:59 pm 
Offline
User avatar

Joined: Mon Sep 27, 2004 2:13 pm
Posts: 1668
you could do:

switch(opcode)
{
case 0x00: goto brk or brk();
...
}

and hope it becomes a jump table.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 12, 2007 8:13 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1849
large switch statements usually get compiled to a jump table.

therefore a single, large switch is usually the way to go. From there I generally use macros or inline functions for addressing mode/instruction combos.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 13, 2007 12:24 am 
Offline
User avatar

Joined: Mon Sep 27, 2004 8:33 am
Posts: 3715
Location: Central Texas, USA
Yep. The straight forward switch is the best place to start:
Code:
switch ( opcode )
{
case 0x00: // BRK
    ...
    break;

case 0x01: // ORA (zp,x)
    ...
    break;
...
}

If you've got over 100 case statements, most compilers will use a jump table for the switch, since that's faster than the 7 comparisons that would otherwise be required to determine the opcode (7 because they would use a binary search, not the 100 that a linear search would require).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 13, 2007 11:57 am 
Offline

Joined: Fri Nov 09, 2007 10:38 am
Posts: 16
Good, thanks. I guess I underestimated the compiler's (gcc) capabilities here.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 13, 2007 3:30 pm 
Offline

Joined: Wed Sep 13, 2006 12:45 pm
Posts: 60
With gcc(this uses a gcc extension), I've done something like this before:

Code:
static const void* GotoTable[256] =
{
 &&Op00, &&Op01, &&Op02, [...]
};

goto *GotoTable[happy_opcode];


Whether or not this is good programming practice is left to the reader. ;)
I actually had an instance where doing this was measurably faster than a switch() statement, so I guess gcc's optimizer is a bit flaky sometimes. But, the NES has enough opcodes, that it should always cause gcc to generate a jump table automatically with an opcode switch() statement.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 14, 2007 2:54 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3188
Location: Brazil
Yes, that's my idea, and I could simplify a lot of code. However, I have no clues about seeing the compiler level of anything...

_________________
Zepper
RockNES developer


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 14, 2007 7:49 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21593
Location: NE Indiana, USA (NTSC)
Fx3 wrote:
Yes, that's my idea, and I could simplify a lot of code. However, I have no clues about seeing the compiler level of anything...

If you're looking for ideas on what not to hand-optimize, and you can read i386 assembly language, you can look at the asm code that GCC generates:

gcc -Wall -O -c hello.c
produces object code in hello.o

gcc -Wall -O -S hello.c
produces asm code in hello.s

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 17, 2007 2:43 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3188
Location: Brazil
Uh... yes, but I meant another point. By using multiple jumps (goto), does it take out a chance to optimize the code for the compiler? A "major" programmer said that to me, as if this piece of code "locks" any optimizing... or almost.

_________________
Zepper
RockNES developer


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group