3

I'm writting a GameBoy color emulator in C, just to introduce myself into this world, it is interpreted, nothing of dynamic or static recompilation :P

Now I'm right in the tedious task of implementing all the CPU opcodes in C code, I have to write all these: http://www.pastraiser.com/cpu/gameboy/gameboy_opcodes.html and I don't want to take them from another emulator.

The question is, is there some way to automate the opcodes writting? Maybe it's a silly question and it will have a silly answer, but I want to work as less as possible. :)

0x77D
  • 1,564
  • 2
  • 18
  • 17
  • 1
    +1 I'm currently working on a JVM now and after spending hours implementing every variation of the add instruction I really hope that someone will be able to say "why of course this can be automated!" Here's hoping... – templatetypedef Mar 25 '11 at 09:32
  • [I know your pain](https://github.com/CRogers/GbcEmulator/blob/master/GbcEmulator/Cpu/Z80.Opcodes.cs) – Callum Rogers Mar 07 '12 at 17:15
  • 100% agree, I found this after searching... – Coolq B Feb 17 '17 at 07:20

3 Answers3

7

I've done this kind of thing before and the way I did it was with macros, but doing it that way you end up with a whole lot of code duplication that overflows the cpu cache and makes things slow. If I were to do it today, I'd get rid of the whole "opcode switch/jumptable" idiom except for obscure/rare opcodes, and write common branchless code for all the normal arithmetic/logical ops using some small lookup tables based on the opcode number. Think something like:

operand1 = regs[operand1_table[opcode]];
operand2 = regs[operand2_table[opcode]];
res[ADD] = operand1+operand2;
res[SUB] = operand1-operand2;
res[OR] = operand1|operand2;
/* ... */
regs[dest_table[opcode]] = res[optype_table[opcode]];

This code is of course over-simplified, but can be expanded to deal with memory operands, etc. Also note that a jump instruction is just an add instruction with the program counter as one of its operands.

For CISC archs like Z80 (or the GB variant thereof) or x86, you're also going to have to deal with condition code flags. However they can be done as a second set of computations like the res[...] = ...; ones above.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 1
    This is absolutely wicked (in the good sense), but if the target instruction set includes division, will the host, out-of-order processor be smart enough to avoid stalling on a series of those, whose result is not used. Or should division be one of the obscure/rare opcodes? – Pascal Cuoq Mar 25 '11 at 13:30
  • I would consider division one of the non-basic-arithmetic instructions. Actually on ancient cpus like Z80, if they even have multiplication I'd consider it rare too. – R.. GitHub STOP HELPING ICE Mar 25 '11 at 13:45
6

I know this is an old and answered question, but for the record, if someone ends up having the same problem:

I made up a quick script to parse this documentation page and generate a JSON with opcodes description.

You can just load this JSON and generate the boilerplate of your GB [dis]assembler code from it, that should clearly save time since JSON is easy to manipulate from most scripting languages.

Code and resulting JSON:

NewbiZ
  • 2,395
  • 2
  • 26
  • 40
  • I'm writing a GB emulator myself and just came across your post. It should be helpful, thanks. Funny to see that you posted it only a few days before I see it ! – Maël Nison Feb 16 '14 at 16:04
  • 1
    Aurélien Vallée's JSON file for GB opcodes had several issues, and finding these out yourself is rather time-consuming. Here's a repo with a fixed JSON file: https://github.com/Prehistoricman/GBEmulatorStuff (comment by [Prehistoricman](http://stackoverflow.com/users/4632769/prehistoricman)) – nhahtdh Mar 05 '15 at 05:00
3

That is why, so far, I have only done emulators or static recompilers for msp430, 6502, and thumb...less typing. to break up the monotony what I will often do is take a program/game I want to see work and execute until it hits an opcode I have not implemented, then implement that opcode and try again.

What is worse, is that it may take you two or three emulators or two or three re-writes of this emulator before you get the feel for how you could have saved a lot of typing and/or how you could have better designed re-used/logic. By trying to execute a favorite rom you get a randomish instruction mix that puts you into various parts of the opcode table and as you re-use code for those opcodes you might...might...be able to improve your design with less re-writes.

As R. is probably describing if you instead create a spreadsheet or some other software parsable table you can write and re-write a simulator code generator from that table. Here again you can start small you dont have to make a complete table, try a handful of different flavors of opcodes and see if you cant figure out a table format that allows your parser to generate code for the simulator. You can later add flags and other things and make the whole process grow as it improves. At the end of the day though, be it a table or actual code, you are eventually going to have to have typed in all of those opcodes.

old_timer
  • 69,149
  • 8
  • 89
  • 168