I have an old C++ project I made a while back. Well, it is a CPU emulator. Whenever a CPU fault happens(such as divide by zero, or debug breakpoint interrupt, etc) in my code it just does a throw and in my main loop I have something like this:
try{
*(uint32_t*)&op_cache=ReadDword(cCS,eip);
(this->*Opcodes[op_cache[0]])();
eip=(uint16_t)eip+1;
}
catch(CpuInt_excp err){
err.code&=0x00FF;
switch(err.code){
case 0:
case 1: //.....
Int16(err.code);
break;
default:
throw CpuPanic_excp("16bit Faults",(err.code|0xF000)|TRIPLE_FAULT_EXCP);
break;
}
}
And a simple opcode example(pulled out of thin air)
if(**regs16[AX]==0){
throw CpuInt_excp(0); //throw divide by zero error
}
What this code basically does is just reads an opcode and if an exception occurred, then call the appropriate interrupt(in the CPU, which just changes the EIP)
Well, this being in the main loop, the try{}catch{} overhead really adds up. This isn’t a premature optimization, I profiled it and gcc’s exception helper functions(without even doing any faults and thus no throws) and the helper functions took up over 10% of the total execution time of a long running emulated program.
So! What would be the best way of replacing exceptions in this case? I would prefer not to have to keep track of return values because I already have a ton of code written, and because keeping track of them is really difficult when functions get really deep.
You haven’t shown your loop, but I’m guessing in pseudocode it’s:
You could move the
try..catchout a level:There I’ve included two loops, because I assume that if an exception occurs you want to be able to carry on (hard to tell without knowing what you’re doing in
Int16, but I think you’re allowing carrying on after non-panic exceptions). Naturally if you don’t need to carry on, you only need one loop.The outer loop just restarts things after the exception. It can check the same condition as the inner loop if that condition is not expensive to check (e.g., it’s a program counter or something), or it can have a flag as in the above if the condition is expensive to check.