I'm sure almost everyone has a big switch() for their opcodes in their CPU emulator.
I was recently thinking about this approach qeed showed me (which I guess was blargg's idea?)
At first I was like "really? goto? wtf". But now that I think about it, it makes some sense. It avoids duplicate code and keeps the switch smaller because there's less inline.
But still... goto? There has to be a better way.
So I thought about it... and what if you made two separate switches... one for the addressing mode lookup, and another for the opcode execution?
This seems like it would keep the switches even smaller, which might help speed up the code. Although I'm not sure if the double-switch would slow it down.
Has anyone tried something like this? I'm curious as to how well it would work.
I was recently thinking about this approach qeed showed me (which I guess was blargg's idea?)
Code:
switch (cpu.opcode)
{
case lda_imm:
get_imm();
goto lda;
case lda_zp:
get_zp():
goto lda;
case adc_imm:
get_imm();
goto adc;
lda: /* do stuff */
break;
adc: /* do stuff */
break;
}
{
case lda_imm:
get_imm();
goto lda;
case lda_zp:
get_zp():
goto lda;
case adc_imm:
get_imm();
goto adc;
lda: /* do stuff */
break;
adc: /* do stuff */
break;
}
At first I was like "really? goto? wtf". But now that I think about it, it makes some sense. It avoids duplicate code and keeps the switch smaller because there's less inline.
But still... goto? There has to be a better way.
So I thought about it... and what if you made two separate switches... one for the addressing mode lookup, and another for the opcode execution?
Code:
switch(cpu.opcode)
{
case lda_imm:
case adc_imm:
get_imm();
break;
//...
}
switch(cpu.opcode)
{
case lda_imm:
lda();
break;
case adc_imm:
adc();
break;
}
{
case lda_imm:
case adc_imm:
get_imm();
break;
//...
}
switch(cpu.opcode)
{
case lda_imm:
lda();
break;
case adc_imm:
adc();
break;
}
This seems like it would keep the switches even smaller, which might help speed up the code. Although I'm not sure if the double-switch would slow it down.
Has anyone tried something like this? I'm curious as to how well it would work.