Fork me on GitHub

Pages

Thursday, October 13, 2011

Opcode patterns 70% finished

genlut.py is really filling out.  It generates the LUT for all 68k opcodes (68000 only), and I'm about 70% done.  77 down, 34 to go.

The OPCODES dict defines the first two bytes of each opcode, both static bits and operands.  The operand strings act as keys into the PATTERNS struct, which contains all possible values for each operand.

The recursive function gen() is fed an opcode pattern which may contain operand strings as well as static bits.  Some operand patterns contain other operand patterns, so gen() keeps recursing until all operand patterns are gone.  Once a set of totally static bits has been created, those bits are added to INSTRUCTIONS, along with the name of the opcode.

The PATTERNS, OPCODES, and INSTRUCTIONS dicts are all named poorly, and the whole solution  isn't ultra-elegant, but it does follow the structure of the 68k PRM pretty intuitively and is easy to edit.  Once it's complete, I should never need to run it again.

Thursday, September 22, 2011

LUT

Decoding is easy. Decoding requires a lot of typing. (I am starting to believe this is true of ever aspect of interpreted emulation...)


For the AEJS decoder, I am creating a look-up table with every possible pattern for each instruction. It was my first idea, but I initially discarded it as "wasteful and inelegant". Later, I accepted it as "really fast".


I'm generating a large set of bit patterns that map to 68k opcodes, like so:

0100101011111010 -> BGND
0100101011111100 -> ILLEGAL
0100111001110000 -> RESET
0100111001110001 -> NOP
0100111001110010 -> STOP
0100111001110011 -> RTE

The current code can be found here: https://github.com/mwcz/AEJS/blob/master/src/genlut.py


Yes, it's written in Python and yes, AEJS is a JavaScript project.  There's a reason.  I see two approaches to generating the LUT (look-up table).


Generate the LUT on launch (dynamic)


This has the advantage of being easier to debug.  It also might be easier if I ever expand the emulator to other chips, like the 68020 or 68030.


It currently takes about 0.466 seconds on my machine to generate ~12,000 patterns.  That means it should take less than 2.5s to generate the full LUT.



Generate the LUT pre-launch (static)

This is what I'm currently working toward.  genlut.py is currently generating about 12,000 opcode bit patterns out of a max of I'm-not-sure-yet-but-slightly-less-than-65,536.

With this method, I would run genlut.py one final time, pipe the output into a static JS file, and regex the contents into a JS array.  The LUT would never have to be generated again, and would exist happily forever-after.

Cons: relies upon the LUT being 100% correct, as any errors would be hard to debug, and would require another run of genlut.py to fix.

Pros: AEJS will launch faster without having to generate the LUT each time.  If I can verify that the LUT is 100% correct, this is obviously the right approach.

I'll continue on with the static method for now, and odds are I'll stick with it.   2.5s is too big a price to pay.


Back to work:



Tuesday, September 20, 2011

Introducing AEJS, an Amiga emulator written in JavaScript.  Wait, wording it like that makes it sound like it's finished.  It isn't.  It won't be for a long time.  AEJS is just a hobby, and will never hold a candle to UAE.

Why the Amiga?  Given that this is my first emulator, it would have been much easier to go with a 6502 or 8080 instead, but I didn't grow up with those; I grew up with a 68k powering an Amiga 500.


Why JavaScript?  Fabrice Bellard didn't make any excuses for writing an x86 emulator in JavaScript, so I won't either.

I'll be using this blog to share updates on the project.  Progress, problems, etc.  Anyone with interest or knowledge of 68k arch or Amiga chipsets is welcome to get involved.

Next up: completing the code to generate an opcode lookup table.