Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. -----------------------------------------------------------------------------
  2. Starscream 680x0 emulation library                              version 0.26d
  3. Copyright 1997, 1998, 1999 Neill Corlett
  4. Modified by Stéphane Dallongeville
  5. -----------------------------------------------------------------------------
  6.  
  7. "Pathetic flesh creatures... can't you see we're INVINCIBLE?  Come,
  8. Decepticons, follow me to victory!"
  9.  
  10.  
  11. How to contact Neill Corlett:
  12. email: corlett@elwha.nrrc.ncsu.edu
  13. www:   http://www4.ncsu.edu/~nscorlet/
  14.  
  15.  
  16. Contents
  17. --------
  18.  
  19.  0.  Terms of Use
  20.  
  21.  1.  What's New
  22.  
  23.  2.  Getting Started
  24.      2.1.  What You Will Need
  25.      2.2.  How to Compile
  26.  
  27.  3.  The Starscream Interface
  28.      3.1.  Function Reference
  29.      3.2.  Contexts
  30.      3.3.  Address Spaces
  31.      3.4.  Executing Code
  32.      3.5.  Read and Write Handlers
  33.      3.6.  The Odometer
  34.      3.7.  Interrupts
  35.      3.8.  Emulating More Than One CPU
  36.      3.9.  RESET and BKPT Instructions
  37.      3.10. Using the Interactive Debugger
  38.      3.11. Emulating the 68010
  39.  
  40.  4.  Tricks of the Trade
  41.      4.1.  Inter-CPU Communication
  42.      4.2.  Other Helpful Tips
  43.      4.3.  Pitfalls
  44.      4.4.  Ways to Abuse Starscream
  45.      4.5.  Emulating Other 68K-Series CPUs
  46.  
  47.  5.  Known Bugs
  48.  
  49.  6.  Credits
  50.  
  51.  
  52. -----------------------------------------------------------------------------
  53. 0.  Terms of Use
  54. -----------------------------------------------------------------------------
  55.  
  56. "Starscream" refers to the following files:
  57. *  STAR.C
  58. *  STARCPU.H
  59. *  CPUDEBUG.C
  60. *  CPUDEBUG.H
  61. *  STARDOC.TXT
  62. *  any object file or executable compiled from the above
  63. *  any source code generated from STAR.C, or object file assembled from such
  64.    code
  65.  
  66. Starscream may be distributed freely in unmodified form, as long as this
  67. documentation is included.
  68.  
  69. No money, goods, or services may be charged or solicited for Starscream, or
  70. any emulator or other program which includes Starscream, in whole or in part.
  71. Using Starscream in a shareware or commercial application is forbidden.
  72. Contact Neill Corlett (corlett@elwha.nrrc.ncsu.edu) if you'd like to license
  73. Starscream for commercial use.
  74.  
  75. Any program which uses Starscream must include the following credit text, in
  76. its documentation or in the program itself:
  77.  
  78. "Starscream 680x0 emulation library by Neill Corlett
  79.  (corlett@elwha.nrrc.ncsu.edu)"
  80.  
  81.  
  82. -----------------------------------------------------------------------------
  83. 1.  What's New
  84. -----------------------------------------------------------------------------
  85.  
  86. Version 0.26d:
  87. *  CHK generation fixed.
  88. *  IDBcc generation fixed (IDBtr added).
  89.  
  90. Version 0.26c:
  91. *  Shift bits instructions fixed.
  92.  
  93. Version 0.26b:
  94. *  IO DWord Write bug fixed.
  95. *  Interrupt processing bug fixed.
  96.    (all lines added are followed by "// Stef Fix (Gens)" )
  97.  
  98. Version 0.26a:
  99. *  Egregious GetContext/SetContext bug fixed.
  100. *  Minor tweaking was done to the alignment rules.
  101.  
  102. Version 0.26:
  103. *  First publicly redistributable version.
  104. *  Added the following exceptions:
  105.       Trace
  106.       Format Error (68010+)
  107. *  Added a Double Fault mechanism.  Currently the only thing that can cause
  108.    this is s68000reset().
  109. *  The memory map interface has changed to support different function codes /
  110.    address spaces (see section 3.3).
  111. *  Many improvements have been made to interrupt handling (see section 3.7).
  112. *  The unused bits of PC are now handled and preserved properly.
  113. *  Added fetch region caching.  Jumps within the same program region are
  114.    now faster.
  115. *  Added a user-definable BKPT instruction handler (68010+).
  116. *  All Illegal Instruction exceptions are now emulated.  The -illegal and
  117.    -noillegal options have been removed.
  118. *  Some features were added to the interactive debugger (see section 3.10).
  119. *  A few experimental 68020-related functions and variables have been added.
  120.    Ignore them for now.
  121.  
  122. Version 0.25 and earlier:
  123. Ask if interested.
  124.  
  125.  
  126. -----------------------------------------------------------------------------
  127. 2.  Getting Started
  128. -----------------------------------------------------------------------------
  129.  
  130. 2.1.  What You Will Need
  131. ------------------------
  132.  
  133. *  A 32-bit C or C++ compiler.  So far, the following compilers have been
  134.    proven to work:
  135.    -  DJGPP 2.01
  136.    -  Watcom 10.6
  137.    -  GCC, running under Linux
  138.    -  Microsoft Visual C++
  139.  
  140. *  Netwide Assembler (NASM) version 0.95 or higher.  NASM is freeware, with
  141.    publicly available source code, and available on a multitude of x86-based
  142.    platforms.  It's available from Programmer's Heaven:
  143.    http://www.programmersheaven.com/
  144.  
  145. *  Basic knowledge about the 680x0.  You don't (theoretically) need to know
  146.    any 680x0 assembly, but it helps.  A lot.
  147.  
  148.    You can get a copy of the M68000 Family Programmer's Reference Manual (in
  149.    Adobe Acrobat .PDF format) from this web page:
  150.    http://www.mot.com/SPS/HPESD/prod/0X0/frames/68K.html
  151.  
  152.  
  153. 2.2.  How to Compile
  154. --------------------
  155.  
  156. Step 1
  157.    Generate the Starscream "code builder" executable by compiling STAR.C.
  158.    (for example:  gcc star.c -o star)
  159.  
  160. Step 2
  161.    Generate the CPU source code.  Run the code builder with the following
  162.    command line:
  163.  
  164.       star source.asm [options]
  165.  
  166.    Replace "source.asm" with the source code filename of your choice.
  167.  
  168.    Options that you might need:
  169.  
  170.       -regcall          Use register calling conventions.
  171.       -stackcall        Use stack-based calling conventions (default).
  172.  
  173.       -hog              Enable Hog mode.  This inlines the fetch-decode-
  174.                         execute loop, resulting in a decent speed increase,
  175.                         at the cost of about 130K of executable size.
  176.       -nohog            Disable Hog mode (default).
  177.  
  178.       -cputype <type>   Specify the CPU type, 68000 or 68010 (default=68000).
  179.  
  180.    Options that you should never need (but they're here anyway):
  181.  
  182.       -addressbits n    Use n-bit addresses.  The default value depends on
  183.                         the CPU type (currently it's just 24).
  184.  
  185.                         "-addressbits 32" might allow some 68020/68070 code
  186.                         to work.  No guarantees, though.
  187.  
  188.       -name <name>      Appends the string <name> to all identifiers.  This
  189.                         overrides the default of s68000 or s68010 (depending
  190.                         on the CPU type).
  191.  
  192. Step 3
  193.    Assemble the CPU source code.  Refer to the NASM documentation for how to
  194.    do this.
  195.  
  196.    If you run out of memory, try using NASMW.EXE instead of NASM.EXE (note,
  197.    however, that the NASMW.EXE executable from v0.97 is somewhat unstable).
  198.    Better yet, just recompile NASM yourself.  Worked for me.
  199.  
  200.    To generate a COFF object for DJGPP or GNUWin32, try this:
  201.  
  202.       nasm -f coff source.asm
  203.  
  204.    or to generate a Win32 object for Watcom or Visual C++:
  205.  
  206.       nasm -f win32 source.asm
  207.  
  208. Step 4
  209.    Strip your executable when you're done!  Starscream spews out symbols all
  210.    over the place (over 7000 of them), and you can save a ton of space by
  211.    stripping them once you're finished debugging.
  212.  
  213.    For GCC, this means use the -s option in the linking phase.
  214.  
  215.  
  216. -----------------------------------------------------------------------------
  217. 3.  The Starscream Interface
  218. -----------------------------------------------------------------------------
  219.  
  220. 3.1.  Function Reference
  221. ------------------------
  222.  
  223. The following is a brief summary of the functions declared in STARCPU.H.  For
  224. more information on a particular function, read the associated section.
  225.  
  226.   int s68000init(void);                           (section 3.4)
  227.      Initializes Starscream.  Always returns 0.
  228.  
  229.   int s68000reset(void);                          (section 3.4)
  230.      Resets the current CPU.
  231.      Return value:
  232.         0     Success
  233.         1     Failure:  Reset vector couldn't be fetched
  234.        -1     Failure:  Double fault
  235.  
  236.   unsigned s68000exec(int n);                     (section 3.4)
  237.      Executes n cycles' worth of instructions on the current CPU.
  238.      Return value:
  239.         = 0x80000000   Success
  240.         = 0x80000001   Out of bounds
  241.         = 0x80000002   Unsupported stack frame (68010+)
  242.         = 0xFFFFFFFF   Double fault
  243.         < 0x80000000   Invalid instruction; the value returned is the address
  244.                        of the instruction
  245.  
  246.   int s68000interrupt(int level, int vector);     (section 3.7)
  247.      Generates a hardware interrupt on the current CPU, with a given priority
  248.      level and vector number.  The interrupt is queued for processing as soon
  249.      as possible.
  250.      Valid levels: 1-7
  251.      Valid vectors:
  252.        0-255  Deliberately vectored interrupt
  253.        -1     Auto-vectored interrupt
  254.        -2     Spurious interrupt
  255.      Return value:
  256.         0     The interrupt was queued successfully.
  257.         1     The interrupt was not queued, because a previously queued
  258.               interrupt exists at the same level.
  259.         2     The interrupt was not queued, because either "level" or "vector"
  260.               were invalid.
  261.  
  262.   void s68000flushInterrupts(void);               (section 3.7)
  263.      Check if there are any unmasked interrupts pending, and if so, process
  264.      them.
  265.  
  266.   int s68000GetContextSize(void);
  267.      Returns the size of the context structure.  Useful for verifying that
  268.      the context struct is packed correctly, i.e.:
  269.      ASSERT(s68000GetContextSize() == sizeof(struct S68000CONTEXT));
  270.  
  271.   void s68000GetContext(void *context);           (section 3.2)
  272.      Copies the current context into another context structure.
  273.  
  274.   void s68000SetContext(void *context);           (section 3.2)
  275.      Copies a context structure into the current context.
  276.  
  277.   int s68000fetch(unsigned address);
  278.      Fetches the word at the specified address, using the memoryfetch array.
  279.      Returns -1 if the address is out of bounds.
  280.  
  281.   unsigned s68000readOdometer(void);              (section 3.6)
  282.      Returns the value of the odometer for the current CPU.  Works anywhere,
  283.      even from within memory read/write, RESET, or BKPT handlers.
  284.  
  285.   unsigned s68000tripOdometer(void);              (section 3.6)
  286.      Returns the value of the odometer for the current CPU, and resets it to
  287.      zero.  Works anywhere.
  288.  
  289.   unsigned s68000controlOdometer(int n);          (section 3.6)
  290.      Returns the value of the odometer for the current CPU.  If n!=0, it also
  291.      resets the odometer to zero.  Works anywhere.
  292.  
  293.   void s68000releaseTimeslice(void);              (section 3.5)
  294.      When called from inside a memory read/write, RESET, or BKPT handler,
  295.      this causes s68000exec to end prematurely.  The early exit is reflected
  296.      in the odometer.
  297.  
  298.   unsigned s68000readPC(void);
  299.      Returns the current program counter.  Works anywhere.
  300.  
  301.  
  302. 3.2.  Contexts
  303. --------------
  304.  
  305. A "context" is a memory structure which holds all the information needed to
  306. emulate a single CPU.  Starscream defines a 68000 context as follows:
  307.  
  308.    struct S68000CONTEXT {
  309.       struct STARSCREAM_PROGRAMREGION *fetch;
  310.       struct STARSCREAM_DATAREGION    *readbyte;
  311.       struct STARSCREAM_DATAREGION    *readword;
  312.       struct STARSCREAM_DATAREGION    *writebyte;
  313.       struct STARSCREAM_DATAREGION    *writeword;
  314.       struct STARSCREAM_PROGRAMREGION *s_fetch;
  315.       struct STARSCREAM_DATAREGION    *s_readbyte;
  316.       struct STARSCREAM_DATAREGION    *s_readword;
  317.       struct STARSCREAM_DATAREGION    *s_writebyte;
  318.       struct STARSCREAM_DATAREGION    *s_writeword;
  319.       struct STARSCREAM_PROGRAMREGION *u_fetch;
  320.       struct STARSCREAM_DATAREGION    *u_readbyte;
  321.       struct STARSCREAM_DATAREGION    *u_readword;
  322.       struct STARSCREAM_DATAREGION    *u_writebyte;
  323.       struct STARSCREAM_DATAREGION    *u_writeword;
  324.       void         (*resethandler)(void);
  325.       unsigned       dreg[8];
  326.       unsigned       areg[8];
  327.       unsigned       asp;
  328.       unsigned       pc;
  329.       unsigned       odometer;
  330.       unsigned char  interrupts[8];
  331.       unsigned short sr;
  332.    };
  333.  
  334. There is a built-in context, called s68000context, which contains information
  335. about the current CPU.  If you're only emulating one 68000, then
  336. s68000context is the only context you need.  On the other hand, if you're
  337. emulating more than one 68000, you'll need to define your own context for
  338. each one.
  339.  
  340. Here is a detailed description of the contents of a S68000CONTEXT structure:
  341.  
  342. *  "s_fetch", "s_readbyte", "s_readword", "s_writebyte", and "s_writeword"
  343.    are used to define the supervisor address space.  "u_fetch", etc. are
  344.    used to define the user address space.  (see section 3.3)
  345.  
  346. *  "resethandler" points to your reset handler routine.  (see section 3.9)
  347.  
  348. *  "pc" is the program counter.
  349.  
  350. *  "dreg" holds the eight data registers, d0-d7, in order.
  351.  
  352. *  "areg" holds the eight address registers, a0-a7, in order.  In supervisor
  353.    mode, areg[7] is the interrupt stack pointer.  Otherwise, it's the user
  354.    stack pointer.
  355.  
  356. *  "asp" is whatever stack register areg[7] isn't.  In supervisor mode, asp
  357.    is the user stack pointer.  Othewise, it's the supervisor stack pointer.
  358.  
  359. *  "odometer" holds the number of cycles executed so far.  It's incremented
  360.    as necessary on calls to s68000exec or s68000flushInterrupts.
  361.  
  362. *  "interrupts" is an array containing information about pending interrupts.
  363.    (see section 3.7)
  364.  
  365. *  "sr" is the status register.  The lower 8 bits are the condition code
  366.    register.
  367.  
  368.  
  369. 3.3.  Address Spaces
  370. --------------------
  371.  
  372. The 68000 communicates with other devices via a number of address spaces.
  373. There are different address spaces for program code and data, as well as
  374. different address spaces for Supervisor and User modes.  Most 68000-based
  375. architectures use the same address space for all these, but the distinction
  376. is there nonetheless.
  377.  
  378. Starscream emulates program address spaces by translating the 68K address
  379. into a native host address, and fetching data directly from host memory (from
  380. an array of words with native byte order).  A program address space is
  381. defined using an array of STARSCREAM_PROGRAMREGION structures:
  382.  
  383.    struct STARSCREAM_PROGRAMREGION {
  384.       unsigned lowaddr;
  385.       unsigned highaddr;
  386.       unsigned offset;
  387.    };
  388.  
  389. Each structure contains the range of addresses in a program region, and an
  390. offset which is added to the 68K address to obtain the equivalent host
  391. address.
  392.  
  393. IMPORTANT NOTE:  Program regions must be stored as an array of words with
  394. native byte order.  Since Intel's byte order is different than Motorola's,
  395. this means every other byte must be swapped.
  396.  
  397. The s68000context fields "s_fetch" and "u_fetch" should be set to point to
  398. arrays of STARSCREAM_PROGRAMREGION structures in order to define the
  399. Supervisor Program and User Program address spaces, respectively.  Each array
  400. may contain any number of entries, and is terminated by an entry containing
  401. -1 for both lowaddr and highaddr, and NULL for the offset.
  402.  
  403. Starscream emulates data address spaces in a completely different way.  Since
  404. the 68000 has no dedicated I/O bus, device interfaces (video/sound chips,
  405. input devices, etc.) are often mapped directly into a data address space.
  406. This raises some complex issues; for example, writing to an emulated serial
  407. port address might require that an extra routine be called, in order to pass
  408. the data through a real serial port, append it to a log file, etc.  To this
  409. end, Starscream defines data address spaces using an array of
  410. STARSCREAM_DATAREGION structures:
  411.  
  412.    struct STARSCREAM_DATAREGION {
  413.       unsigned lowaddr;
  414.       unsigned highaddr;
  415.       void *memorycall;
  416.       void *userdata;
  417.    };
  418.  
  419. Each structure contains the low and high addresses in a region, as before.
  420. Rather than simply adding a constant offset to translate a 68K address into
  421. a native one, Starscream offers two different ways to handle accesses to a
  422. data region:
  423.  
  424.    1.  Call a user-defined handler routine whenever this region is accessed.
  425.  
  426.           unsigned read_handler(unsigned address);
  427.           void write_handler(unsigned address, unsigned data);
  428.  
  429.           memorycall = pointer to user handler
  430.           userdata   = unused
  431.  
  432.        (For some important information about read and write handlers, refer
  433.        to section 3.5.)
  434.  
  435.    2.  Handle accesses internally by reading/writing to an area of native
  436.        memory.  Don't trap anything.  This is ideal for a simple RAM or ROM
  437.        area as it requires the least processing.
  438.  
  439.           memorycall = NULL
  440.           userdata   = pointer to native memory area where reads or writes
  441.                        will occur
  442.  
  443.        NOTE: The native memory area must be byte swapped, same as program
  444.              regions are.
  445.  
  446. The s68000context fields "s_readbyte", "u_readbyte", "s_writebyte", etc.
  447. should be set to point to arrays of STARSCREAM_DATAREGION structures in order
  448. to define the Supervisor Data and User Data address spaces.  Each array may
  449. contain any number of entries, and is terminated by an entry containing -1
  450. for lowaddr and highaddr, and NULL for memorycall and userdata.
  451.  
  452. And now, for an example of address space definition.  Consider the following
  453. make-believe memory map:
  454.  
  455.  000000-03FFFF:   Program ROM
  456.  300000-307FFF:   Main RAM
  457.  400000-407FFF:   Extra RAM
  458.  800000-81FFFF:   Video RAM
  459.  A00000-A00007:   Sound chip
  460.  
  461. Assume that:
  462.  *  Program ROM is in an array called program_rom
  463.  *  Main RAM is in an array called main_ram
  464.  *  Extra RAM is in an array called extra_ram
  465.  *  Video RAM is in an array called video_ram
  466.  *  You've set up two routines to write to the sound chip:
  467.       void soundchip_writebyte(unsigned address, unsigned data);
  468.       void soundchip_writeword(unsigned address, unsigned data);
  469.  
  470. The first step is to build the program address space.  Program code is
  471. probably only going to be fetched from Program ROM, Main RAM, or Extra RAM.
  472. The address space would thus be defined:
  473.  
  474.    struct STARSCREAM_PROGRAMREGION pretend_programfetch[] = {
  475.       {0x000000, 0x03FFFF, (unsigned)program_rom - 0x000000},
  476.       {0x300000, 0x307FFF, (unsigned)main_ram - 0x300000},
  477.       {0x400000, 0x407FFF, (unsigned)extra_ram - 0x400000},
  478.       {-1, -1, NULL}
  479.    };
  480.  
  481. The last entry must be {-1, -1, NULL}.
  482.  
  483. The next step is to build the data address space.  This is accomplished with
  484. four arrays of STARSCREAM_DATAREGION structures:  one for byte reads, word
  485. reads, byte writes, and word writes.  For example:
  486.  
  487.    struct STARSCREAM_DATAREGION pretend_readbyte[] = {
  488.       {0x000000, 0x03FFFF, NULL, program_rom},
  489.       {0x300000, 0x307FFF, NULL, main_ram},
  490.       {0x400000, 0x407FFF, NULL, extra_ram},
  491.       {0x800000, 0x81FFFF, NULL, video_ram},
  492.       {-1, -1, NULL, NULL}
  493.    };
  494.  
  495.    struct STARSCREAM_DATAREGION pretend_readword[] = {
  496.       {0x000000, 0x03FFFF, NULL, program_rom},
  497.       {0x300000, 0x307FFF, NULL, main_ram},
  498.       {0x400000, 0x407FFF, NULL, extra_ram},
  499.       {0x800000, 0x81FFFF, NULL, video_ram},
  500.       {-1, -1, NULL, NULL}
  501.    };
  502.  
  503.    struct STARSCREAM_DATAREGION pretend_writebyte[] = {
  504.       {0x300000, 0x307FFF, NULL, main_ram},
  505.       {0x400000, 0x407FFF, NULL, extra_ram},
  506.       {0x800000, 0x81FFFF, NULL, video_ram},
  507.       {0xA00000, 0xA00007, soundchip_writebyte, NULL},
  508.       {-1, -1, NULL, NULL}
  509.    };
  510.  
  511.    struct STARSCREAM_DATAREGION pretend_writeword[] = {
  512.       {0x300000, 0x307FFF, NULL, main_ram},
  513.       {0x400000, 0x407FFF, NULL, extra_ram},
  514.       {0x800000, 0x81FFFF, NULL, video_ram},
  515.       {0xA00000, 0xA00007, soundchip_writeword, NULL},
  516.       {-1, -1, NULL, NULL}
  517.    };
  518.  
  519. The last entry of each array must be {-1, -1, NULL, NULL}.
  520.  
  521. The above structures take advantage of Starscream's internal handling for the
  522. Program ROM, Main RAM, Extra RAM, and Video RAM, and use the custom handler
  523. when writing to the sound chip.
  524.  
  525. Now that you've defined your address spaces, you need to tie it in with the
  526. context (since each CPU can have different address spaces).  This is done by
  527. setting the address space pointers (s_fetch, u_fetch, etc.) to point to your
  528. addres space definitions.
  529.  
  530.    s68000context.s_fetch = pretend_programfetch;
  531.    s68000context.u_fetch = pretend_programfetch;
  532.  
  533.    s68000context.s_readbyte  = pretend_readbyte;
  534.    s68000context.u_readbyte  = pretend_readbyte;
  535.    s68000context.s_readword  = pretend_readword;
  536.    s68000context.u_readword  = pretend_readword;
  537.    s68000context.s_writebyte = pretend_writebyte;
  538.    s68000context.u_writebyte = pretend_writebyte;
  539.    s68000context.s_writeword = pretend_writeword;
  540.    s68000context.u_writeword = pretend_writeword;
  541.  
  542. In this example, the Supervisor and User address spaces are set up to point
  543. to the same definitions.  For most 68000-based architectures, this is
  544. correct.
  545.  
  546. If you are dynamically allocating memory for your emulated RAM or ROM areas
  547. (using malloc() or a similar function), you will have to set up the address
  548. space definitions at run time.  This is left as a trivial exercise for the
  549. reader.
  550.  
  551. Veteran users of the UAE 680x0 core might wonder why there is no "readlong"
  552. or "writelong".  This is because the real 68000 has a 16-bit data bus, and
  553. therefore breaks up each 32-bit access into two 16-bit accesses.  Using
  554. separate handlers for 32-bit accesses is cumbersome and unnecessary.  For
  555. speed considerations, Starscream's internal memory read/write handlers access
  556. 32 bits at a time wherever possible (using the readword/writeword map).
  557.  
  558.  
  559. 3.4.  Executing Code
  560. --------------------
  561.  
  562. Before you execute any code, you must call s68000init().  It only needs to
  563. be called one time.
  564.  
  565. Once that's done, and you've set up the memory map, call s68000reset() to
  566. reset the CPU.  If everything works, it should read the initial stack pointer
  567. from address 0x000000, and the initial program counter from 0x000004, using
  568. the Supervisor Program address space.  (You can verify this by examining
  569. s68000context.areg[7] and s68000context.pc.)
  570.  
  571. At this point, you can call the interactive debugger to try disassembling or
  572. stepping through code, and to make sure everything is in the right place.
  573. (see section 3.10 for details)
  574.  
  575. To execute 68000 code, call s68000exec(n), where n is the number of cycles.
  576. s68000exec will return one of the following:
  577.  
  578.  = 0x80000000:  Success.
  579.  = 0x80000001:  Out of range - the program "went off into the weeds".
  580.                 More specifically, the program jumped to an address which was
  581.                 not defined in the s_fetch or u_fetch array.
  582.  = 0x80000002:  Unsupported stack frame (68010+).  This happens when an RTE
  583.                 instruction encounters a stack frame format that hasn't been
  584.                 implemented (see section 5).
  585.  = 0xFFFFFFFF:  Double fault.  The CPU is dead and will stay dead until it
  586.                 gets reset again.
  587.  < 0x80000000:  Invalid instruction.  The value returned is the address of
  588.                 the instruction.  For 32-bit addresses, the highest bit is
  589.                 cut off (s68000context.pc contains the complete address,
  590.                 however).
  591.  
  592. If you get a return code of 0x80000001, 0x80000002, or 0xFFFFFFFF, then the
  593. 68000 CPU will be in an unstable state and should be reset.
  594.  
  595. The real 68000 generates an exception for illegal instructions.  As of v0.26,
  596. this exception is always emulated.  You will only get a return code less than
  597. 0x80000000 in an unexpected circumstance; upon encountering an invalid
  598. instruction that isn't supposed to be.  For example, a RESET instruction will
  599. cause this if the user-defined RESET handler is null (see section 3.9 for
  600. details on RESET handlers).
  601.  
  602. Whenever you call s68000exec, it increments the odometer (see section 3.6).
  603.  
  604.  
  605. 3.5.  Read and Write Handlers
  606. -----------------------------
  607.  
  608. Memory read and write handlers (as described in section 3.3) are a special
  609. case, as they involve Starscream calling your code instead of the other way
  610. around.  Since Starscream is not re-entrant, there are some rules which all
  611. read and write handlers must follow.
  612.  
  613. 1.  They must not call any of the following routines:
  614.       s68000reset           s68000exec
  615.       s68000SetContext      s68000GetContext
  616.  
  617. 2.  They must not attempt to read or modify s68000context directly.  All
  618.     data in s68000context is undefined.
  619.  
  620. The primary purpose of a read handler is to return data, and the primary
  621. purpose of a write handler is to take data and store it somewhere.  However,
  622. read and write handlers do have some control over the emulation process,
  623. beyond the data that they send or receive:
  624.  
  625. *  You can call s68000interrupt() as much as you like (see section 3.7).
  626.  
  627. *  You can cause s68000exec to quit early, by calling the
  628.    s68000releaseTimeslice() function.  This is useful if you need to transfer
  629.    control over to another emulated CPU.
  630.  
  631. *  You can read and/or clear the odometer, with some specialized functions
  632.    (see section 3.6).
  633.  
  634. *  You can read the program counter with s68000readPC(), but it probably
  635.    won't be located exactly at the beginning of the instruction.
  636.  
  637.  
  638. 3.6.  The Odometer
  639. ------------------
  640.  
  641. Every context contains an integer field called "odometer".  Whenever you
  642. call s68000exec, the number of elapsed clock cycles is added to
  643. s68000context.odometer.
  644.  
  645. Note:  When calling s68000exec, the number of elapsed cycles is not
  646. necessarily the same as the number of cycles you specify.  Imagine this
  647. scenario:  You call s68000exec(100).  The next instruction in the code stream
  648. is...
  649.  
  650.    movem.l ($100000).L,d0-d7/a0-a7
  651.  
  652. s68000exec would quit after that one instruction, returning the success code,
  653. 80000000h (assuming nothing else went wrong), and s68000context.odometer
  654. would be incremented by 148.
  655.  
  656. You can freely change the odometer between calls to s68000exec, but not from
  657. within read/write handlers (as it's part of the context).  If you need to use
  658. the odometer from a read or write handler, there are some specialized
  659. functions for that:
  660.  
  661. s68000readOdometer()     - Returns the value of the odometer.
  662. s68000tripOdometer()     - Returns the value of the odometer, and sets it to
  663.                            zero in the process.
  664.  
  665. s68000controlOdometer(n) - If n==0, it works just like s68000readOdometer.
  666.                            If n!=0, it works just like s68000tripOdometer.
  667.                            (We have Neil Bradley to thank for this gem...)
  668.  
  669.  
  670. 3.7.  Interrupts
  671. ----------------
  672.  
  673. Hardware interrupts can be generated at any time, including within read/write
  674. handlers, by calling s68000interrupt(l, v) where l is the interrupt priority
  675. level, and v is the vector number.  Levels 1-7 are valid; vector numbers
  676. 0-255 are valid.  Vector number -1 means "auto-vectored".  -2 will generate a
  677. Spurious Interrupt.
  678.  
  679. The interrupt in question will be made pending until the Processor Priority
  680. Level allows it to be processed.  You can tell which interrupt levels are
  681. pending, if any, by examining s68000context.interrupts[0].  Bits 1-7
  682. correspond to interrupt level 1-7; bit 0 is set if the CPU is in a stopped
  683. state (waiting for an interrupt).  The vector numbers are stored in
  684. s68000context.interrupts[n] where n is the interrupt level.
  685.  
  686. s68000interrupt returns one of the following values:
  687.  
  688.    0    The interrupt was added successfully.
  689.    1    The interrupt was not added, because there was already a pending
  690.         interrupt at the same level.
  691.    2    The interrupt was not added, because the parameters were invalid.
  692.  
  693. Pending interrupts are checked at the following times:
  694.  
  695. *  s68000exec checks for pending interrupts before executing any code.  The
  696.    cycles taken by interrupt processing are subtracted from the total "cycle
  697.    budget", though s68000exec is still guaranteed to execute at least one
  698.    instruction.
  699.  
  700. *  Interrupts generated from within a read/write, RESET, or BKPT handler will
  701.    be checked when the current instruction is finished.
  702.  
  703. *  You can force a pending interrupt check by calling s68000flushInterrupts.
  704.    This has no effect if called from within a read/write, RESET, or BKPT
  705.    handler.
  706.  
  707. Starscream can call a user-defined function when handling interrupts.
  708. The handler must take no arguments, and return void.
  709.  
  710.    s68000context.inthandler = my_int_handler;
  711.  
  712.  
  713. 3.8.  Emulating More Than One CPU
  714. ---------------------------------
  715.  
  716. If you want to emulate multiple 68000s, you'll need to create a context and a
  717. memory map for each one (see sections 3.2 and 3.3).  For example:
  718.  
  719.    struct S68000CONTEXT myContext[number_of_68000s];
  720.  
  721. When you use your own contexts, it's a good idea to initialize all the bytes
  722. in the new contexts to zero:
  723.  
  724.    memset (myContext, 0, sizeof(myContext));
  725.  
  726. To use one of your own contexts, you must follow these three steps:
  727.  
  728. 1.  Copy your context into s68000context:
  729.     s68000SetContext(myContext);
  730.  
  731. 2.  Use a function which reads or modifies the context - s68000exec,
  732.     s68000reset, s68000interrupt, etc.
  733.  
  734. 3.  Copy s68000context back into your context:
  735.     s68000GetContext(myContext);
  736.  
  737. Expanding on the example in section 3.2 - say you're emulating two 68000s,
  738. and you've set up two contexts for them:
  739.  
  740.    struct S68000CONTEXT myContext[2];
  741.  
  742. To reset both CPUs, you'd do this:
  743.  
  744.    for(i = 0; i < 2; i++) {
  745.       s68000SetContext(&myContext[i]);
  746.       s68000reset();
  747.       s68000GetContext(&myContext[i]);
  748.    }
  749.  
  750. An emulation loop involving both CPUs might look something like this.  (Note:
  751. This is a CRUDE example.)
  752.  
  753.    while(!done) {
  754.       /* Emulate primary 68000 */
  755.       s68000SetContext(&myContext[0]);
  756.       s68000exec(100000);
  757.       s68000GetContext(&myContext[0]);
  758.  
  759.       /* Emulate secondary 68000 */
  760.       s68000SetContext(&myContext[1]);
  761.       s68000exec(100000);
  762.       s68000GetContext(&myContext[1]);
  763.    }
  764.  
  765. The overhead of copying CPU contexts is compensated by the fact that you can
  766. emulate the CPUs in large timeslices.
  767.  
  768.  
  769. 3.9.  RESET and BKPT Instructions
  770. ---------------------------------
  771.  
  772. Starscream can call a user-defined function to emulate the RESET instruction,
  773. and to notify when a BKPT instruction is executed.  The handlers must take no
  774. arguments, and return void.  For example:
  775.  
  776.    void my_reset_handler(void) {
  777.       /* Reset some hardware */
  778.    }
  779.  
  780. Note:  RESET and BKPT handlers must follow the same rules as memory
  781. read/write handlers (see section 3.5).
  782.  
  783. To register a handler function, set the "resethandler" and/or "bkpthandler"
  784. field of the appropriate context to point to the function, i.e.:
  785.  
  786.    s68000context.resethandler = my_reset_handler;
  787.  
  788. You can also set "resethandler" or "bkpthandler" to NULL, in which case:
  789.  
  790. *  A RESET instruction will cause an Invalid Instruction case.  s68000exec
  791.    will halt and return its address.
  792.  
  793. *  A BKPT instruction will behave normally, but without notification.
  794.  
  795. Calling s68000readPC() during a RESET or BKPT handler will return the address
  796. directly after the RESET or BKPT instruction.  So, to determine the exact
  797. BKPT opcode, you can do this:
  798.  
  799.    opcode = s68000fetch(s68000readPC() - 2);
  800.  
  801.  
  802. 3.10.  Using the Interactive Debugger
  803. -------------------------------------
  804.  
  805. Included in the Starscream package is an interactive 68000 cross-debugger and
  806. built in disassembler, with an interface similar to the MS-DOS DEBUG utility.
  807. CPUDEBUG.C contains everything needed for the debugger.  If you don't need
  808. it, you can leave out CPUDEBUG.C and CPUDEBUG.H altogether.
  809.  
  810. Before using the debugger, make sure to set up your memory map, and call
  811. s68000init() and s68000reset().
  812.  
  813. To start the debugger, call the cpudebug_interactive routine, which is
  814. defined in CPUDEBUG.H as:
  815.  
  816.    int cpudebug_interactive(
  817.       int cpun,
  818.       void (*put)(const char*),
  819.       void (*get)(char*, int),
  820.       void (*execstep)(void),
  821.       void (*dump)(void)
  822.    );
  823.  
  824. "put", "get", "execstep", and "dump" are all optional - you can pass NULL
  825. values for any or all of them.  Their purpose is explained below.
  826.  
  827. If you're only emulating one CPU, use a value of 1 for "cpun", and keep
  828. calling cpudebug_interactive until the return value is -1.
  829.  
  830. If you're debugging more than one CPU, assign an ID number to each (starting
  831. at 1), including any non-68000 CPUs.  Switch to the context of the CPU you
  832. want to debug, and then call cpudebug_interactive with the appropriate ID
  833. number in "cpun".  Then, take one of the following actions depending on the
  834. return value:
  835.  
  836.  -1   Quit
  837.   0   Switch to the next CPU in your list (ID + 1), wrap around if necessary,
  838.       and call cpudebug_interactive again.  Or, if the CPU in question is not
  839.       a 680x0, then use whatever debugger is appropriate.
  840.   N   Switch to CPU #N.  If N is invalid, don't switch.  In either case, call
  841.       the appropriate debugger.
  842.  
  843. While you're at the debug prompt, enter "?" for a list of commands.
  844.  
  845. Normally, the interactive debugger uses stdin and stdout for its input and
  846. output.  If you need to use another source of input or output, you can write
  847. custom replacement functions for puts() and gets(), and pass their addresses
  848. via "put" and "get".
  849.  
  850. Normally, the debugger calls s68000exec() directly to step through each
  851. instruction.  If your emulator manages its own timing, you can write a custom
  852. replacement single-step function, and pass its address via "execstep".
  853.  
  854. The debugger command 'h' (Hardware dump) will call the function specified by
  855. "dump", if it exists.
  856.  
  857.  
  858. 3.11.  Emulating the 68010
  859. --------------------------
  860.  
  861. To generate a 68010 emulator, use the "-cputype 68010" option when building
  862. your source code file.  The names of all identifiers will begin with s68010
  863. instead of s68000 (unless overridden by the -name option).
  864.  
  865. When emulating the 68010, use the S68010CONTEXT structure instead of
  866. S68000CONTEXT.
  867.  
  868. S68010CONTEXT has six new fields:
  869.  
  870.    unsigned char sfc;
  871.    unsigned char dfc;
  872.    unsigned      vbr;
  873.    void        (*bkpthandler)(void);
  874.    unsigned char loopmode;
  875.    unsigned char contextfiller10[3];
  876.  
  877. "vbr", "sfc", and "dfc" are control registers.
  878.  
  879. "bkpthandler" is a user-defined routine for BKPT notification (see section
  880. 3.8).
  881.  
  882. "loopmode" is used internally for loop mode timing.  (Did I mention the loop
  883. mode timing is insanely accurate?)
  884.  
  885. "contextfiller10" is there just to maintain alignment.
  886.  
  887. An invalid MOVEC register code will cause s68010exec to return with an
  888. invalid instruction error, pointing to the MOVEC instruction (not the code
  889. itself).
  890.  
  891. NOTE:  The interactive debugger currently does not support the 68010.
  892.  
  893.  
  894. -----------------------------------------------------------------------------
  895. 4.  Tricks of the Trade
  896. -----------------------------------------------------------------------------
  897.  
  898. 4.1.  Inter-CPU Communication
  899. -----------------------------
  900.  
  901. Many arcade and console game systems which use multiple CPUs use a sort of
  902. "mailbox" technique to allow the main CPU to send messages to the sub CPU
  903. (sound effect numbers, etc.)
  904.  
  905. When one of your 68000s writes to another CPU's mailbox, it's generally a
  906. good idea to transfer control over to the other CPU temporarily.  This can be
  907. achieved by calling s68000releaseTimeslice() from your I/O handler.  This
  908. will cause s68000exec to exit, even if it's not finished.  (Always check the
  909. odometer to see how many cycles were really executed!)
  910.  
  911.  
  912. 4.2.  Other Helpful Tips
  913. ------------------------
  914.  
  915. When defining your memory map(s):
  916.  
  917. *  Take advantage of the built-in RAM and ROM handling as much as possible.
  918.    They involve much less "red tape" than using your own handlers.
  919.  
  920. *  The addresses don't have to be in order.  You can rearrange them so that
  921.    the most commonly-accessed areas are at the beginning.  This will shave a
  922.    few cycles off each access.
  923.  
  924. *  If you have two areas of fetchable RAM or ROM that are right next to each
  925.    other, consider coalescing them into one area.  This will make the memory
  926.    map simpler and facilitate fetch region caching.  It will also allow the
  927.    680x0 code to wander from one area into the next.  Starscream only checks
  928.    boundaries after JMP, JSR, RTS, RTR, RTD, RTE, and exceptions.
  929.  
  930. When executing code:
  931.  
  932. *  Instead of calling s68000exec with a fixed number of cycles, keep track of
  933.    how many cycles overflowed from the last call to s68000exec, and subtract
  934.    them:
  935.  
  936.       #define TIMESLICE 100000
  937.  
  938.       s68000context.odometer = 0;
  939.       while(!done) {
  940.          if (s68000context.odometer < TIMESLICE) {
  941.             s68000exec(TIMESLICE - s68000context.odometer);
  942.          }
  943.          s68000context.odometer -= TIMESLICE;
  944.       }
  945.  
  946. *  Use big timeslices.  The fewer calls you make to s68000exec, the better.
  947.  
  948.  
  949. 4.3.  Pitfalls
  950. --------------
  951.  
  952. *  Make sure to include "starcpu.h" in any of your C modules that use
  953.    Starscream.  Also remember that starcpu.h is subject to change in new
  954.    versions.  (Hint hint.)
  955.  
  956. *  Remember to call s68000init before executing any code.  s68000init doesn't
  957.    automatically call s68000reset, so you must call s68000reset also.
  958.  
  959. *  Remember to set up your memory map before calling s68000reset.  The memory
  960.    map is required in order to read the initial SSP/PC from the vector table.
  961.  
  962. *  When you store a context via s68000SetContext, remember to read it back
  963.    via s68000GetContext.
  964.  
  965. *  The interactive debugger can only read memory areas that are defined in
  966.    your STARSCREAM_PROGRAMREGION array.  Everything else will appear as FFFF.
  967.    The upshot of this is that a memory dump is guaranteed not to trigger any
  968.    I/O hardware.
  969.  
  970. *  Simplify your STARSCREAM_PROGRAMREGION map as much as possible, in case
  971.    the emulated code decides to wander from one area to another.
  972.  
  973. *  Remember the rules for read/write handlers (section 3.5), and remember
  974.    that they also apply to RESET and BKPT handlers (section 3.9).
  975.  
  976. *  When you use your own contexts, make sure to explicitly set "resethandler"
  977.    and "bkpthandler" to NULL if you're not using them.  (This is why it's a
  978.    good idea to initialize every byte of a new context to zero.)
  979.  
  980.  
  981. 4.4.  Ways to Abuse Starscream
  982. ------------------------------
  983.  
  984. For the adventurous...
  985.  
  986. *  Upon encountering an unrecognized opcode, s68000exec will return the
  987.    address of the opcode, instead of the success code, 0x80000000.  If you
  988.    need to emulate an instruction that's not implemented yet, you can take
  989.    advantage of this behavior and implement it in your own code.
  990.  
  991.    Outside of s68000exec, the context can be modified freely.  You can use
  992.    the s68000fetch routine to fetch the unrecognized opcode and anything
  993.    after it (see section 3.1 for the declaration of s68000fetch).
  994.  
  995. *  Using 32-bit addresses (-addressbits 32) saves one cycle for every memory
  996.    access, and simplifies the PC re-basing process.  This is safe only for
  997.    software that is "32-bit clean", however.
  998.  
  999. *  Make a stand-alone 68000 disassembler out of CPUDEBUG.C.  ;)
  1000.  
  1001.  
  1002. 4.5.  Emulating Other 68K-Series CPUs
  1003. -------------------------------------
  1004.  
  1005. Note:  None of these are officially supported.
  1006.  
  1007. 68008
  1008.   Try "-cputype 68000 -addressbits 20" or "-cputype 68000 -addressbits 22",
  1009.   depending on the chip package.  You'll have to lower the clock speed to get
  1010.   more accurate timing (try dividing it in half), and you might have to
  1011.   compensate for the 8-bit data bus.
  1012.  
  1013. 68EC000
  1014.   "-cputype 68000" should work.  If it's running in 8-bit mode, try dividing
  1015.   the clock speed in half.
  1016.  
  1017. SCC68070
  1018.   Try "-cputype 68000 -addressbits 32".  Not sure about timing issues.
  1019.  
  1020. 6833X (CPU32)
  1021.   Try "-cputype 68010".  Timing might be a little slow.  A few instructions
  1022.   aren't supported.
  1023.  
  1024. 68020 and higher
  1025.   Try "-cputype 68010 -addressbits 32".  This is a bit of a stretch, though,
  1026.   since the 68020 supports many new address modes and instructions.  Failing
  1027.   that, wait until official 68020 support is added.  ;)
  1028.  
  1029.  
  1030. -----------------------------------------------------------------------------
  1031. 5.  Known Bugs
  1032. -----------------------------------------------------------------------------
  1033.  
  1034. *  Address and Bus Errors are not implemented.  For arcade game emulation,
  1035.    this is probably OK, but if you're emulating a home computer system, this
  1036.    could be cause for concern.
  1037.  
  1038. *  The MOVES instruction (68010+) is not implemented.
  1039.  
  1040. *  Stack frame format 8 (68010+) is not supported.  Starscream will never
  1041.    generate such a stack frame itself; however, if this format is
  1042.    encountered during a RTE, s68010exec() will return with an "Unsupported
  1043.    stack frame" error.
  1044.  
  1045. *  There are a few timing inaccuracies:
  1046.    68000:  DIVS and DIVU: +/- 5%
  1047.    68010:  MULS and MULU are inaccurate, but I'm not sure by how much.
  1048.  
  1049. *  Flags which Motorola documents as "Undefined" are, in fact, undefined.
  1050.    I could probably look up how they're calculated, and implement them, but
  1051.    the need has not arisen (yet).
  1052.  
  1053.  
  1054. -----------------------------------------------------------------------------
  1055. 6.  Credits
  1056. -----------------------------------------------------------------------------
  1057.  
  1058. Thanks to:
  1059.  
  1060. *  Heinz Seltmann, for letting me borrow his M68000 Microprocessor User's
  1061.    Manual (Ninth Edition) for way too long.
  1062.  
  1063. *  Neil Bradley, Mike Cuddy, James Boulton, Richard Bush, and Dave (of DTMNT/
  1064.    DGen fame) for various tips and ideas.
  1065.  
  1066. *  Thierry Lescot, who gave me the idea to distribute Starscream in the first
  1067.    place.
  1068.