4

I started writing a DCPU-16 emulator using this v1.7 spec. I started laying down the architecture, and I don't like the fact that I'm using very long switch statements. This is my first time writing an emulator, and so I don't know if there's better way to be doing it. While the switches aren't that large, due to the DCPU's small number of opcodes (and the fact that I haven't actually implemented the instructions yet), I can imagine if I were writing an emulator for a larger instruction set the switch statements would be huge.

Anywhom, here's my code.

EDIT: I forgot to get my question across:

  • Is there a better way to design an emulator than using a massive switch?
Bertie Wheen
  • 1,215
  • 1
  • 13
  • 20
  • There's a comprehensive set of answers on replacing switch statements here: http://stackoverflow.com/questions/126409/ways-to-eliminate-switch-in-code – TheDarkKnight Jun 19 '13 at 09:33
  • 2
    @Merlin069 I would argue that most of these (= polymorphism) are a bad idea for an emulator/VM. You don't really want a polymorphic object of at least two words size for every instruction, and there is no flexibility to be gained because the instruction set doesn't change over time. –  Jun 19 '13 at 09:36
  • @delnan, I would agree with that, though I provided it as a reference, in-case it sparked any ideas for Bertie. – TheDarkKnight Jun 19 '13 at 09:37
  • @Merlin069 I mostly agree with delnan, though I might have a play around with the Map approach. – Bertie Wheen Jun 19 '13 at 09:40
  • @BertieWheen, I was just about to write that, though I was thinking that if you're using C++ 11, you could do a map of op codes to lamda expressions that define the operation, if that's possible, or just a map to function pointers. – TheDarkKnight Jun 19 '13 at 09:47
  • @BertieWheen If by `Map` you mean `std::map`, I'd be weary. It's a binary search tree, lookup is not only worse than O(1) in theory but also quite cache-hostile and branch-heavy in practice. An array (or a hash table, if the opcodes are very sparse and you want to save a bit of space -- doesn't seem to be the case here) is smaller and faster. –  Jun 19 '13 at 09:56

1 Answers1

2

This approach seems reasonable to me. It is certainly how I would do it (I have written a few CPU emulators and similar types of code).

The nearest alternative is a set of function pointers, but some of your cases will probably be rather simple (e.g. cpu_regs.flags &= ~CARRY or if (cpu_regs.flags & CARRY) do_rel_jump(next_byte());, so using function pointers will slow you down.

You can bunch all the "No Operation Specified yet" to one place, that will make it a lot shorter in number of lines, but the number of cases will of course still be the same [unless you put it in default:].

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Yeah, I wasn't sure whether to just let them fall through to the default case or have the default case purely as a "something's gone seriously wrong" clause. Though, I suppose you could call executing an unspecified opcode as seriously wrong.. – Bertie Wheen Jun 19 '13 at 09:39
  • Depending on the architecture (and I'm not familiar with this particular one), "unspecified opcode" should probably cause an exception/trap of some sort. But you can still use a common handler. Obviously, since your `switch` covers all the possible alternatives, the only way you could actually end in `default` is if the compiler/processor somehow messes up `opcode = instruction & 0x1f;`, which seems rather unlikely. – Mats Petersson Jun 19 '13 at 09:47
  • 2
    Oh, and a tip: Make your registers into an array instead of individual names. Will make it much easier to "get to them" from your integer value you got out by anding the instruction. You can always write a function that gives you "name from index" [or even have a table]. – Mats Petersson Jun 19 '13 at 09:49
  • The 'name from index' is probably the route I'm going to take, though I was considering other methods. We'll see. I'm going to leave it a bit longer to see if any other answers come in, but if not I'll accept yours. Thanks – Bertie Wheen Jun 19 '13 at 10:00