Skip to main content
gamedev.net
🔒 Locked

optimizing MCU emulator code

Started by TheDmD 5 replies 1.3k views
Original Post
TheDmD
TheDmD
hello everybody A few days ago I finished my microcontroller processor emulator. I used a simple 'switch' instruction to choose operation for opcode. This method is slowly. Do anybody know any faster techniques? Sorry for mistakes in language (if I did).
Extrarius
Extrarius
If the total code inside the switch statement isn't very much (several hundred lines of C++, say), switch is the fastest way to take a number and perform some operation based on the number. Otherwise, it might be better to use a table of function pointers with each opcode represented by a single function (possibly with the functions taking as one parameter the number of the opcode so the same function could handle multiple similar opcodes) so that more will fit into the cache (presuming some opcodes are used more often than others).

The problem with speed could be due to the details of the implementation, but we can't know that for sure without the code.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
TheDmD
TheDmD
Actually I using switch with small parts of code.

switch (opcode){  // (...)  // CLR A  case 0xE4:    ACC = 0;    cycles = 1;    m_pc++;    break;  // CPL A  case 0xF4:    ACC = (byte)~ACC;    cycles = 1;    m_pc++;    break;  // RL A  case 0x23:    ACC = (byte)((ACC << 1) | (ACC >> 7));    cycles = 1;    m_pc++;    break;  // RLC A  case 0x33:    tmp_b = (byte)(((PSW & PSW_Flags.CY) != 0) ? 1 : 0);    if ((ACC & 0x80) != 0)      PSW |= PSW_Flags.CY;    else      PSW &= ~PSW_Flags.CY;    ACC = (byte)((ACC << 1) | tmp_b);    cycles = 1;    m_pc++;    break;  // (...)}


I forgot to say very important thing. All code was written in C#. I thinking about rewrite MCU code in C++ with inline asm. I planing to use call vectors and minimize opcode resolving code to minimum. It is critical part of whole implementation.

I am interesting about miscallaneous techniques. Which probably could be faster. Currently simulation is ten time slower than real-time.

Why others emulators (more complicated than my) working with efficiency excedding 1000% and my have only 10%-15%? C# is slower than other languages? Maybe using .NET is not good idea?
Demus79
Demus79
AFAIK C# is slower language than C++. C# is similar to Java language when the code is executed. C# compiler doesn't create native code for the computer but bytecode (which of course can be optimized and compiled to native code). It could be that the C# program is actually running on a certain kind of virtual machine too which cannot reach the speed of native code.

With the switch, on C++ for example, if correctly coded (find a faq about it), the cpu makes only one jump and doesn't test all the cases, so it is pretty efficient.

If you have a random collection of different values to test, you could perhaps implement some sort of binary tree to reduce the amount of tests required to find the correct code.
TheDmD
TheDmD
Hm. I know IL is language working on virtual machine. I attempt to compile it to native code. Well, it fail ;)
I realy must learn more about .NET programming techniques.

A word about 'switch'. If I arrange all cases in raising order that will be enought for compiler to generator optimized code? I trying to write my own switch-like command in inline asm. I use a list of jmp instructionts which move execution point to correct operation. It will be great if compiler do this same thing (or similar) without using inline asm.

Exacly switch contain all values of 8-bit opcode (excluding one). So, I have 255 cases. Now they are unordered. I think any binary tree is not needed.
Ravyne
Ravyne
If I'm not mistaken, bit-level operations are one of the slower points of C# so doing things like instruction decoding, bit packing/unpacking, etc may be the bottleneck. A language like C or C++ will likely be much faster here.

Which micro-controller are you emulating? what is the instruction-set encoding scheme like?
throw table_exception("(? ???)? ? ???");
Shannon Barber
Shannon Barber
If you are looking for a high-level arch change that would drastically improve performance, you could re-compile the uC binary into an x86 assembly/binary.
It wouldn't really be an emulator anymore, but a translator.

Sticking with C# and emulation, I would first check and make sure you have all the C# optimizations enabled. Looking at the code I see some repition that could be eliminated. For example, I assume you always have to increase the PC (and actually the PC is usually incremented after the instruction fetched is initiated but before that instruction is actually executed). But a good optimizer should do that for you.

You mentioned that compiling the code to a native .exe failed? See if you can resolved what went wrong there. The Windows CLR implementation is quite sophisticated, IIRC it does JIT compliation and produces native code - but I do not know any of the caveat's to that.

To make the switch statement most effective, the numbers switched on need to be contiguous, then the compiler can make an efficent jump-table. Or you can make a jump-table your self. If you vector to a function for each op code you're going to add tremendous overhead to each op code. If you use a function table, you gaurantee a function call as well, since the compiler must load the addresd then jump to it - there's no possibility of inlining them.

Typically the op code are designed with some method to thier madness. You probably shouldn't switch on the entire op code, but part of it. Maybe you can do some gross-culling which decides which type of op code it is and switch to an (inlined) function that handles that famility of op codes.

if(opcode & 0x0100)       mem_op();else if (opcode & 0x8000) alu_op();else if (opcode & 0xf000) fpu_op();else                      whatevers_left();
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.