<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>
Date   : Mon, 18 Jul 1994 11:06:46 EST
From   : Stephen Quan <quan@...>
Subject: Steve's emulators.

I don't know if anyone is following some of the things I have been
writing, but I am working on 2 emulators and am starting a third.
Why?  Because they have completely different design architectures,
and I particularly like my 2nd emulator's internal design, which
holds my secret [now to be reveal] of *not* storing the Status
Register anywhere!

1st emulator -
  This is my standard emulator with a few optimisations here and
  there.  Standard being, it was my first obvious C implementation.
  I have started with

  while (1)
  {
    switch (fetch_opcode)
    {
      case .....
    }
  }


2nd emulator -
  Now, here's the big secret!  What happens if you knew the carry was
  cleared.  You don't have it stored in a variable, you just knew it
  was cleared???  BCC will be just a jump!

  eg.
      case BCC: branch(relative()); break;
      case BCS: PC++; break;

  Well what I did was I extend this idea to NVZC.  I assumed that
  they were all know quantities and wrote every combination into 16
  different emulators all built into one.  For instance

     case CLC: goto emulator_with_carry_cleared; break;
     case SEC: goto emulator_with_carry_set; break;

  I never store, update or check the condition codes of NVZC.  I just
  do a lot of jumps!!!!!

  To my dismay the overall performance has not been improved because
  a few problems in representing this idea totally in C, and this
  emulator only differs from my first emulator by a +/- 5 seconds
  than my previous emulator running.  I am having a few problems
  which was indirectly related to my post on 256-branches.  I know
  this can be done in assembly, but if somehow I could do it in C,
  I bet this emulator will get unrivalled speed!

  Especially that 256^3 loop where have the instructions executed are
  actually BNE instructions.  BNE will be implemented the same way as
  BCC above (based on we know whether Z is set or cleared).


3rd emulator -
  At my dismay, I have no way of storing labels in a big array and
  jumping to them.  I have found that I can store procedure names
  into an array and call them.  So I can replace

     switch (opcode)
     {
       case  :
     }

  With

     run_opcode[opcode]();

  Ok, so now I am losing performance by making a function call, but
  I do make a again that it calls exactly the right function without
  bothering to have one big whopping switch loop.  I have yet to
  implement this and determine whether the gain in trashing switch
  outways the loss in using procedures.  I am hoping that my compiler
  realises that my procedures require nothing more than pushing and
  pulling the PC.

  Also, this emulator I can further my pursuit in knowing NVZC before
  jumping.  How you may ask???  Ok, here comes my next secret!!!  :-)

     N0V0Z0C0_run_opcode[opcode]();

  Of course this will be a 256 array of procedure names that know that
  all the status registers are cleared and will run the appropriate
  functions.

     N1V0Z0C1_run_opcode[opcode]();

  This one knows that N and C are set, and V and Z are cleared.

The actual C syntax on how I implement this, I am with-holding until
I have tried it out myself.  :-)  :-)  If I have time to get a good
book on 386 programming I'd do it in assembly as well!  :-)  :-)
-- 
Stephen Quan (quan@...                 ), SysAdmin, Analyst/Programmer.
Centre for Spatial Information Studies, University of Tasmania, Hobart.
GPO BOX 252C, Australia, 7001.  Local Tel: (002) 202898 Fax: (002) 240282
International Callers use +6102 instead of (002).
<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>