Best way to replace using heavy exceptions?

I have an old C ++ project that I did some time ago. Well, this is a processor emulator. Whenever a CPU error occurs (for example, dividing by zero or debugging an interrupt interrupt, etc.), in my code it only has 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 code example (drawn out of thin air)

 if(**regs16[AX]==0){ throw CpuInt_excp(0); //throw divide by zero error } 

What this code basically does is simply read the operation code and, if an exception occurs, then call the appropriate interrupt (on the CPU, which just changes the EIP)

Well, this is in the main loop, the try{}catch{} premium really adds. This is not a premature optimization, I profiled it and the auxiliary gcc exception functions (without any failures and, therefore, without throws), and the auxiliary functions took more than 10% of the total execution time of a long emulated program.

So! What would be the best way to replace exceptions in this case? I would prefer not to keep track of the return values, because I already have a ton of code, and because tracking them really when the functions get very deep.

+4
source share
3 answers

You did not specify your loop, but I assume in the pseudocode this is:

 while (some_condition) { // Your try..catch block: try { // Do an op } catch (CpuInt_excp err) { // Handle the exception } } 

You can move try..catch to the level:

 done = false; while (!done) { try { while (some_condition) { // Do an op } done = true; } catch (CpuInt_excp err) { // Handle the exception } } 

There I included two loops, because I assume that if an exception occurs, you want to be able to continue (it's hard to say without knowing what you are doing in Int16 , but I think that you allow wraps after non-panic exceptions). Naturally, if you do not need to continue, you only need one cycle.

The outer loop just restarts things after the exception. It can check the same conditions as the inner loop if this condition is not expensive to check (for example, it is a program counter or something else), or it can have a flag, as indicated above, if the condition is expensive to check.

+3
source

How about moving try / catch from your inner loop? The catch will require more bookkeeping, and some additional overhead will return to your inner zone, not starting at the top, but you will only pay when the exception actually fires, and not all the time.

+1
source

It looks like you are writing processor state to member variables since your opcode methods take no parameters. At the risk of declaring the obvious, why not do the same for the exception state? Then you do not have to deal with the return value. Instead, you just need opcode functions to set the exception state, return, and let the main loop check the exception state.

0
source

Source: https://habr.com/ru/post/1299808/


All Articles