

   ##### ####### ##   ## #### ######   ###   ####      ####   #####  ###  ##
  ##   #  ##   # ###  ##  ##  # ## #  ## ##   ##      ##     ##   ##  ##  ##
 ##       ##     #### ##  ##    ##   ##   ##  ##     ##      ##   ##  ## ## 
 ##       ####   #######  ##    ##   ##   ##  ##     ######   #####   ####  
 ##  ###  ##     ## ####  ##    ##   #######  ##     ##   ## ##   ##  ####  
  ##  ##  ##   # ##  ###  ##    ##   ##   ##  ##  ## ##   ## ##   ##  ## ## 
   ##### ####### ##   ## ####  ####  ##   ## #######  #####   #####  ###  ##

                            [ Genital68K Readme ]
                   Copyright 2000, 2001 Bart Trzynadlowski


This is the documentation for Genital68K Version 0.35, please read it. Terms
of use are explained a little further below, it is required that you read and
abide by them in order to use this software.
    
Genital68K is a Motorola 680X0 emulator. It currently emulates the 68000 and
68010 microprocessors. It was written for Intel X86-based (Pentium or better)
systems. Originally designed for Genital, it is now available for public use.

Contact Bart Trzynadlowski:
    Email: trzy@mailandnews.com
    WWW:   http://trzy.overclocked.org
           http://trzy.overclocked.org/gen68k


-------------------
  0. Terms of Use
-------------------

Genital68K is Copyright 2000, 2001 Bart Trzynadlowski.

"Genital68K" refers to: MAKE68K.C, GEN68K.H, README.TXT, any binaries compiled
from those files, any source code emitted from MAKE68K.C, and any object file
created from such code.

To use Genital68K, you must agree to the following:

    - Genital68K shall be distributed freely, unmodified, and intact.
    - Charging money, goods, or services for Genital68K is forbidden.
    - Claiming ownership or authorship of Genital68K is forbidden.
    - Genital68K may not be distributed in any medium for which money, goods,
      or services are solicited.
    - The author, Bart Trzynadlowski, will not be held liable for damages.
    - Credit must be given to the author either in the program itself (where
      the user can see it) or in its documentation.
    
You are encouraged to contact Bart Trzynadlowski if you wish to use Genital68K
in a commercial product (to negotiate licensing.)

Bart Trzynadlowski reserves the right to use Genital68K in any way he sees
fit. If you do not agree with all of these terms, please remove Genital68K
from your possession.


------------------------
  1. Table of Contents
------------------------

    0. Terms of Use
    1. Table of Contents
    2. Making Genital68K
    3. Command Line Options
    4. Using Genital68K
        4.1  Basic Data Types
        4.2  Definitions
        4.3  Context
        4.4  Instruction Fetching
        4.5  Data Access
        4.6  PC-Relative Reads
        4.7  Byte Swapped Memory
        4.8  The RESET and BKPT Instructions
        4.9  Initializing and Resetting Genital68K
        4.10 Running the Emulator
    5. Function Reference
    6. Hints and Tips
        6.1  Alternative Identifiers
        6.2  Multiple Processors
        6.3  Maximizing Speed and Minimizing Size
    7. Additional Notes
        7.1  Change History
        7.2  Un-emulated Features
        7.3  Errata
        7.4  Bibliography
    8. Special Thanks


------------------------
  2. Making Genital68K
------------------------

The Genital68K 680X0 emulator is usually distributed in a compressed archive,
simply extract it and you should have MAKE68K.C, GEN68K.H, and this README.TXT
file.

The first step is to get the source code emitter, Make68K, up and running. It
should compile with any 32-bit C compiler (compilers other than gcc will often
produce warnings, these can be ignored.) The following have been confirmed:

    - DJGPP (gcc v2.8.1)                            [ MS-DOS ]
    - gcc v2.7.2.1                                  [ FreeBSD ]
    - Microsoft VisualC++ 6.0 Professional Edition  [ Windows 95 ]
    - WATCOM C/C++32 Version 10.6                   [ MS-DOS ]

If you get link errors concerning pow(), make sure to include the appropriate
math library. Try "-lm" if you are using GNU tools.

Once Make68K has been built, run it with the name of the file you wish to emit
on the command line. For example:

    make68k gen68k.asm

Make68K can take a number of options. Try "make68k -h" to see a list. Section
3 of this text describes them in more detail.

Assemble the emitted file with NASM. Version 0.97 or better should work, 0.98
is known to work.

Genital68K contains identifiers with leading and trailing underscores as
well as without any, so all the object formats supported by NASM should work.

Remember to include GEN68K.H to use Genital68K.


---------------------------
  3. Command Line Options
---------------------------

Genital68K can be tailored in a variety of ways to suit your needs through the
use of the following command line options:

    -mpu <type>     Processor type. Valid types are 68000 and 68010.
                    [Default=68000]
    -addr <bits>    Address bus width. This simulates the specified number of
                    address lines by cutting off any unsupported address bits
                    when accessing memory or updating the PC. The 68000 and
                    68010 have a 24-bit address bus. [Default=24]
    -illegal        Emulates illegal instruction traps. Line 1010 and Line
                    1111 emulator exceptions are processed as is the normal
                    illegal instruction exception. [Default]
    -noillegal      Does not emulate illegal instruction traps but instead
                    returns an error from Genital68KRun(). The ILLEGAL opcode
                    still generates an illegal instruction trap regardless of
                    wether -illegal or -noillegal has been specified.
    -skip           Skips over idle DBRA loops by setting the counter register
                    to 0xFFFF, adjusting the timer appropriately, and moving
                    to the next instruction.
    -noskip         Does not skip over idle loops. This eliminates problems
                    with compatibility and is recommended. [Default]
    -brafetch       Uses the fetch memory map array to update the PC on Bcc,
                    BRA, BSR, and DBcc instructions.
    -nobrafetch     Bcc, BRA, BSR, and DBcc branches are handled by adding the
                    displacement to the internal normalized PC. This is less
                    safe, in theory, but you should not normally have any
                    problems. It is also faster and generates less code than
                    -brafetch. [Default]
    -pcfetch        PC-relative reads are handled through a special fetch map.
                    Please read section 4.6 for more information.
    -nopcfetch      PC-relative reads are treated as normal data reads.
                    [Default]
    -multiaddr      Separate address spaces for supervisor and user. This has
                    not been extensively tested, so let me know how it works.
                    [Default]
    -singleaddr     Single address space for supervisor and user.
    -defmap         Definable memory map arrays are used to handle reading and
                    writing to the address space. [Default]
    -handler        Uses handlers for reading/writing bytes, words, and long-
                    words. The fetch memory map array must still be set up.
    -stackcall      Use stack-based calling conventions. [Default]
    -regcall        Use register-based calling conventions. EAX contains the
                    first argument, the second is in EDX.
    -id <string>    Adds the specified string to the beginning of all
                    identifiers. Up to 16 characters are allowed. See section
                    6.1 for more information on this.

Please read further to learn more about the details of some of these options.


-----------------------
  4. Using Genital68K
-----------------------

A general overview of Genital68K is provided here. More information on certain
topics is provided throughout the document.


4.1 Basic Data Types

The following data types are provided by Genital68K:

    GENITAL68K_UINT32       Unsigned 32-bit
    GENITAL68K_INT32        Signed 32-bit
    GENITAL68K_UINT16       Unsigned 16-bit
    GENITAL68K_INT16        Signed 16-bit
    GENITAL68K_UINT8        Unsigned 8-bit
    GENITAL68K_INT8         Signed 8-bit


4.2 Definitions

Genital68K functions return and accept defined arguments. Use these instead of
hard-coded values. Different functions return and accept different values, so
make sure to check with the function reference first.

    GENITAL68K_NULL             0
    GENITAL68K_OKAY             Success
    GENITAL68K_SUPERVISOR       Supervisor address space
    GENITAL68K_USER             User address space
    GENITAL68K_ERROR_FETCH      Fetch error (PC out of bounds)
    GENITAL68K_ERROR_INVINST    Invalid instruction
    GENITAL68K_ERROR_INTLEVEL   Invalid interrupt level was specified
    GENITAL68K_ERROR_INTVECTOR  Invalid interrupt vector was specified
    GENITAL68K_ERROR_INTPENDING Specified interrupt level already pending
    GENITAL68K_UNINITIALIZED    Uninitialized interrupt vector
    GENITAL68K_SPURIOUS         Spurious interrupt vector
    GENITAL68K_AUTOVECTOR       Autovectored interrupt


4.3 Context

Processor contexts are special structures which contain all the data necessary 
to manage the emulated 680X0. The procedure for emulating a 680X0 processor
with Genital68K involves setting up a context, mapping it in, emulating some
code, and perhaps mapping the context out.

    Context Definitions:
    --------------------

    struct GENITAL68K_CONTEXT_68000
    {
        void                *fetch;
        void                *read_byte, *read_word, *read_long;
        void                *write_byte, *write_word, *write_long;
        void                *super_fetch;
        void                *super_read_byte, *super_read_word,
                            *super_read_long;
        void                *super_write_byte, *super_write_word,
                            *super_write_long;
        void                *user_fetch;
        void                *user_read_byte, *user_read_word,
                            *user_read_long;
        void                *user_write_byte, *user_write_word,
                            *user_write_long;
        GENITAL68K_UINT32   intr[8], cycles, remaining;
        GENITAL68K_UINT32   d[8], a[8], sp, sr, pc, status;
        void                *Reset;
    };

    struct GENITAL68K_CONTEXT_68010
    {
        void                *fetch, *pcfetch;
        void                *read_byte, *read_word, *read_long;
        void                *write_byte, *write_word, *write_long;
        void                *super_fetch, *super_pcfetch;
        void                *super_read_byte, *super_read_word,
                            *super_read_long;
        void                *super_write_byte, *super_write_word,
                            *super_write_long;
        void                *user_fetch, *user_pcfetch;
        void                *user_read_byte, *user_read_word,
                            *user_read_long;
        void                *user_write_byte, *user_write_word,
                            *user_write_long;
        GENITAL68K_UINT32   intr[8], cycles, remaining;
        GENITAL68K_UINT32   d[8], a[8], sp, sr, pc, fc, vbr, status;
        void                *Reset, *Bkpt;
    };

If you are emulating different address spaces for supervisor and user modes,
the super_ and user_ pointers must be set to point at the respective memory
maps. The other memory map pointers (fetch, read_byte, write_byte, etc.) will
be managed internally by Genital68K.

If you are only emulating a single address space for both privilege modes,
you do not have to set up the super_ and user_ pointers but must set up the
others.

The "intr" array holds pending interrupt information. Entries 0-6 are for
interrupt levels 1-7, they contain the vector of the pending interrupt, or 0
if no interrupt at the given level is pending. Entry 7 contains the number of
pending interrupts. You should not modify this yourself, use the interrupt
functions.

The "cycles" and "remaining" members are used to control execution time.
The total amount of request cycles is held in "cycles" and the number left is
held in "remaining."

Data and address registers are kept in the "d" and "a" array, the PC is kept
in "pc", and the SR is kept in "sr" (the low word is used, the upper word
should be kept 0.) Whichever stack pointer is not in A7 is stored in "sp."
Thus, if the processor is in Supervisor mode, A7 is the SSP and "sp" contains
the USP. For the 68010, "fc" is both SFC (first 3 bits of byte 0) and DFC
(first 3 bits of byte 1.) The 68010's VBR is kept in "vbr."

Additional information on the processor status is reflected in the "status"
member. Its format is:
    
    Bit 0:  R (Running) flag -- 0 = not running, 1 = running
    Bit 1:  S (Stopped) flag -- 0 = not stopped, 1 = stopped via the STOP
            instruction
    Bit 2:  I (Interrupt) flag -- 0 = not processing interrupts, 1 = process-
            ing interrupts (Genital68KProcessInterrupts())

Finally, the "Reset" pointer points to a Reset handler. If the RESET
instruction is executed, this handler will be called. If the pointer is set to
GENITAL68K_NULL, it will not be called. The "Bkpt" pointer is for the 68010's
BKPT instruction.

Contexts can be mapped in and out of Genital68K's internal data space by using
Genital68KSetContext() and Genital68KGetContext(). Once they are mapped in, no
changes will be reflected in your context structures until you map them out.

NOTE: You CANNOT access context members while the context is mapped in unless
there are functions provided for that purpose (such as Genital68KSetFetch(),
Genital68KFreeTimeSlice(), Genital68KReadPC(), etc.)

If there is no function for the operation you want to perform on the context,
you simply cannot do it until the context is mapped out. You may NOT map
contexts in and out from memory handlers while Genital68K is running. Please
consult the function reference for more information.

Genital68K provides an internal context called "genital68kcontext_68000" if
emulating a 68000, or "genital68kcontext_68010" if emulating a 68010. These
are where you copy your context when you use Genital68KSetContext(). They
should only be used if you are emulating one processor.

When setting up memory maps, you can modify context pointers only if the
context was defined by you. If you wish to use the internal context, you will
have to use special functions to perform the same tasks. This is because
Genital68K expects pointers in the internal context to be mangled (for
performance reasons.) Genital68KSetContext()/Genital68KGetContext() handle
this task automatically.

Here is an example of defining a context and mapping it in and out:

    struct GENITAL68K_CONTEXT_68000 mycontext;

    /* ... Set up everything ... */

    Genital68KSetContext(&mycontext);
    /* ... Run some code ... */
    Genital68KGetContext(&mycontext);


4.4 Instruction Fetching

Genital68K needs to know how to fetch instruction from 680X0 memory space. An
array of fetch regions must be set up describing where valid program areas are
located.

    Fetch Region Definition:
    ------------------------

    struct GENITAL68K_FETCHREGION
    {
        GENITAL68K_UINT32   base;
        GENITAL68K_UINT32   limit;
        GENITAL68K_UINT32   ptr;
    };

The "base" is the start address of the fetch region. The "limit" is the end
address. The "ptr" must be set to a host machine pointer value with the base
subtracted from it.

NOTE: Memory must be byte swapped. See section 4.7 for more information.

Here is an example of how a hypothetical system's fetch map might look:

    struct GENITAL68K_FETCHREGION my_fetch[] =
    {
        { 0x000000, 0x3fffff, rom - 0x000000 },
        { 0xff0000, 0xffffff, ram - 0xff0000 },
        { -1,       -1,       GENITAL68K_NULL }
    }

The last element is required to let Genital68K know where the array ends.

To hook the fetch map up to your context, you would code:

    mycontext.super_fetch = my_fetch;
    mycontext.user_fetch = my_fetch;

If you are only using one unified address space for both supervisor and user
modes, all you have to do is:

    mycontext.fetch = my_fetch;

For the internal context, you must use the appropriate functions:

    Genital68KSetFetch(my_fetch, GENITAL68K_SUPERVISOR);
    Genital68KSetFetch(my_fetch, GENITAL68K_USER);

Or, if one address space is being used:

    Genital68KSetFetch(my_fetch, GENITAL68K_NULL);  /* second arg. ignored */


4.5 Data Access

Data accessing (byte, word, and long word read/writes) can be handled in a
number of ways. The first method is handled through definable memory map
arrays, somewhat similar to instruction fetching. This is the default method
(-defmap.)

    Data Region Definition:
    -----------------------

    struct GENITAL68K_DATAREGION
    {
        GENITAL68K_UINT32   base;
        GENITAL68K_UINT32   limit;
        GENITAL68K_UINT32   ptr;
        void                *handler;
    };

You may either set up a pointer, exactly the same as with instruction fetch
regions. But, if the pointer is not set up (GENITAL68K_NULL), Genital68K will
assume you want to use a handler. Simply set "handler" to the address of the
function you want to use, nothing has to be mangled.

Handler functions vary for different sizes of data:

    /*
     * Read byte
     */

    GENITAL68K_UINT8 ReadByte(GENITAL68K_UINT32 addr)
    {
        /* ... */
    }

    /*
     * Read word
     */

    GENITAL68K_UINT16 ReadWord(GENITAL68K_UINT32 addr)
    {
        /* ... */
    }

    /*
     * Read long word
     */

    GENITAL68K_UINT32 ReadLong(GENITAL68K_UINT32 addr)
    {
        /* ... */
    }

    /*
     * Write byte
     */

    void WriteByte(GENITAL68K_UINT32 addr, GENITAL68K_UINT8 data)
    {
        /* ... */
    }

    /*
     * Write word
     */

    void WriteWord(GENITAL68K_UINT32 addr, GENITAL68K_UINT16 data)
    {
        /* ... */
    }

    /*
     * Write long word
     */

    void WriteLong(GENITAL68K_UINT32 addr, GENITAL68K_UINT32 data)
    {
        /* ... */
    }

All handlers are passed addresses that are clipped to whichever value you
chose when emitting the emulator. By default, the address space is 24-bit.

The 68000 and 68010 break accesses down long word accesses into 2 consecutive
word accesses, yet Genital68K still uses long word handlers to provide
opportunities for optimization.

NOTE: Memory must be byte swapped. See section 4.7 for more information.

To hook up the memory maps, you would code:

    mycontext.super_read_byte = my_read_byte;
    mycontext.super_read_word = my_read_word;
    mycontext.super_read_long = my_read_long;
    mycontext.super_write_byte = my_write_byte;
    mycontext.super_write_word = my_write_word;
    mycontext.super_write_long = my_write_long;

    mycontext.user_read_byte = my_read_byte;
    mycontext.user_read_word = my_read_word;
    mycontext.user_read_long = my_read_long;
    mycontext.user_write_byte = my_write_byte;
    mycontext.user_write_word = my_write_word;
    mycontext.user_write_long = my_write_long;

If only one address space is being emulated, try:

    mycontext.read_byte = my_read_byte;
    mycontext.read_word = my_read_word;
    /* ... */

When using an internal context, use the appropriate functions:

    Genital68KSetReadByte(my_read_byte, GENITAL68K_SUPERVISOR);
    Genital68KSetReadWord(my_read_word, GENITAL68K_SUPERVISOR);
    /* ... */


The second method of handling data is to use functions exclusively. Use the
-handler option when emitting Genital68K. Six functions (as shown above) must
be provided and directly hooked up to the context just as with memory maps.
Now, whenever the address space is read or written, your function will be
called and it is up to you to handle everything.


4.6 PC-Relative Reads

In some rare situations, PC-relative address reading cannot function properly
through the normal data access regions/handlers. An example of when this can
occur is when the emulated system uses partially encrypted ROMs (CPS-2.)

Genital68K must be emitted with the -pcfetch option and a special fetch region
for PC-relative reads must be set up. Writes are still handled using the data
regions/handlers. The region is a GENITAL68K_FETCHREGION and thus no handlers
can be used. Memory pointers must be provided in the exact same way as you
would for a normal fetch region.

The array of fetch regions must be attached to the "pcfetch" pointers of
the context:

    mycontext.pcfetch = pcfetch;
    mycontext.super_pcfetch = pcfetch;
    mycontext.user_pcfetch = pcfetch;

When using an internal context, use Genital68KSetPCFetch() and
Genital68KGetPCFetch().

This is a pretty poor hack, but it should do the job in most cases. This
should not be needed for most systems.


4.7 Byte Swapped Memory

Host memory which Genital68K can access directly must be byte swapped! The
MSB (most significant byte) and LSB (least significant byte) of each 16-bit
aligned word must be reversed.

    Sample Byte Swapping Function:
    ------------------------------

    /*
     * void SwapMemory(GENITAL68K_UINT8 *mem, GENITAL68K_INT32 size);
     *
     * Byte swaps a given region of memory to work with Genital68K's native
     * access capabilities.
     */

    void SwapMemory(GENITAL68K_UINT8 *mem, GENITAL68K_INT32 size)
    {
        GENITAL68K_INT32    i, j;

        /*
         * Swap bytes in each word
         */

        for (i = 0; i < length; i += 2)
        {
            j = buffer[i];
            buffer[i] = buffer[i + 1];
            buffer[i + 1] = j;
        }
    }

Byte swapping is an optimization which greatly benefits Genital68K in terms of
speed. It relies on the fact that the 68000 and 68010 use a 16-bit data bus.
To access individual bytes in byte swapped memory, XOR the address with 1.
Words can be read or written normally. Long words are best accessed as 2
consecutive words.


4.8 The RESET and BKPT Instructions

When the RESET or BKPT instruction is executed, the respective handler is
called. If the handler is found to be GENITAL68K_NULL, no action is taken.        
This is useful for emulating the functionality of the RESET (some systems need
to reset hardware when it is executed) and BKPT (some systems might need to
react to the Breakpoint Acknowledge Cycle) instructions. The BKPT handler is
called before the 68010 processes the breakpoint exception.

You can also perform high level emulation (HLE) by strategically inserting
RESET (or BKPT, if dealing with a 68010) instructions into the emulated code.
Use Genital68KReadPC() to make sure you know which RESET/BKPT was executed.
Genital68KReadPC() will point to the next instruction.

When setting up the handlers, no special functions are needed, even if the
internal context is being manipulated.

    mycontext.Reset = &MyRESETHandler;

    genital68kcontext_68000.Reset = &MyRESETHandler;

The RESET handler takes no arguments and returns nothing. The BKPT handler is
passed the breakpoint vector number (0-7.)

    /*
     * Sample RESET handler
     */

    void MyRESETHandler()
    {
        /* ... Reset some hardware ... */
    }

    /*
     * Sample BKPT handler
     */

    void MyBKPTHandler(INT32 num)
    {
        /* ... */
    }


4.9 Initializing and Resetting Genital68K

Prior to doing anything, call Genital68KInit() to initialize Genital68K. This
only needs to be done once per program session.

Next, set up your memory maps. Then, reset the 680X0 processor by calling the
Genital68KReset() function. Genital68K fetches the initial PC and SP from the
supervisor fetch memory map, not through the long word read map. Genital68K
will return an error if it could not reset. This means you have set up your
memory map incorrectly.

    /*
     * Initialize Genital68K (VERY important)
     */

    Genital68KInit();

    /* ... set up memory maps ... */

    /*
     * Reset the processor
     */

    if (Genital68KReset() != GENITAL68K_OKAY)
        Error();

    /* ... begin emulating ... */


4.10 Running the Emulator

To execute code, use Genital68KRun(). Pass it the number of cycles you wish
to run for. Genital68K will execute at least as many cycles as you wanted, but
often executes a bit more. You can use Genital68KGetElapsedCycles() to find
out exactly how many were emulated. See the function reference for more
information.

Genital68KInterrupt() can be used to trigger an interrupt. The first argument
is the level number, and the second argument is the vector. For the vector,
you may use GENITAL68K_AUTOVECTOR for an auto-vectored interrupt,
GENITAL68K_SPURIOUS for a spurious interrupt, and GENITAL68K_UNINITIALIZED for
an uninitialized interrupt.

    /*
     * Run Genital68K for 1000 cycles
     */

    Genital68KRun(1000);

    /*
     * Level 6 auto-vectored interrupt
     */

    Genital68KInterrupt(6, GENITAL68K_AUTOVECTOR);

Both Genital68KRun() and Genital68KInterrupt() can return error information.
See the function reference for more information.


-------------------------
  5. Function Reference
-------------------------

All of Genital68K's functions are described here. Functions which are said not
to work under given circumstances will have undefined results if used under
those conditions. Usually, this means the context will be trashed, so be very
careful!

When Genital68K is running, any handlers you may have set up are considered
part of Genital68K. Thus, when it is said a function cannot be called while
Genital68K is running, this means it cannot be called from a handler.

    GENITAL68K_INT32 Genital68KInit();
        Initializes the emulator. This must be called before anything else.
        Input:
            Nothing.
        Returns:
            GENITAL68K_OKAY
        Restrictions:
            For future compatibility, call this only once per program session.

    GENITAL68K_INT32 Genital68KReset();
        Resets the 680X0. It uses the supervisor instruction fetch region to
        obtain the start-up vectors. Make sure everything is set up. A fetch
        error indicates either that the reset vectors could not be fetched or
        the PC reset vector points to an unhandled region of memory.
        Input:
            Nothing.
        Returns:
            GENITAL68K_OKAY
            GENITAL68K_ERROR_FETCH (PC is out of bounds)
        Restrictions:
            Do not use while Genital68K is running.

    GENITAL68K_INT32 Genital68KRun(GENITAL68K_INT32 cycles);
        Executes at least the specified number of cycles. To get the actual
        number of cycles that were emulated, use Genital68KGetElapsedCycles().
        Input:
            Number of cycles.
        Returns:
            GENITAL68K_OKAY
            GENITAL68K_ERROR_FETCH (PC is out of bounds)
            GENITAL68K_ERROR_INVINST (invalid instruction, if -noillegal was
            specified)
            GENITAL68K_ERROR_STACKFRAME (68010 only, unsupported/invalid stack
            frame, see section 7.2)
        Restrictions:
            Do not use while Genital68K is running.

    GENITAL68K_INT32 Genital68KProcessInterrupts();
        Processes any pending interrupts (unless the priority level does not
        agree with the SR priority bits.)
        Input:
            Nothing.
        Returns:
            GENITAL68K_OKAY
            GENITAL68K_ERROR_FETCH
        Restrictions:
            None. (If called while Genital68K is running, it has no effect.)

    
    GENITAL68K_INT32 Genital68KInterrupt(GENITAL68K_INT32 level,
                                         GENITAL68K_UINT32 vector);
        Generates an interrupt with the specified level and vector. The level
        must be 1-7 and the vector cannot be less than 2. For the vector, you
        may specify the vector itself, GENITAL68K_AUTOVECTOR for an
        autovectored interrupt, GENITAL68K_SPURIOUS for a spurious interrupt,
        or GENITAL68K_UNINITIALIZED for an uninitialized interrupt. 
        Input:
            Level.
            Vector.
        Returns:
            GENITAL68K_OKAY
            GENITAL68K_INTLEVEL (invalid level)
            GENITAL68K_INTVECTOR (invalid vector)
            GENITAL68K_INTPENDING (interrupt already pending at this level;
            this is not an error and will frequently occur, it is best not to
            check for this)
        Restrictions:
            None.
    
    GENITAL68K_INT32 Genital68KCancelInterrupt(GENITAL68K_INT32 level);
        Cancels the pending interrupt at the specified level.
        Input:
            Level.
        Returns:
            GENITAL68K_OKAY
            GENITAL68K_INTLEVEL (invalid level)
        Restrictions:
            None.

    GENITAL68K_UINT32 Genital68KReadPC();
        Returns the current PC. If this is called from within a handler, the
        PC may point at the next instruction or to one of the operand words.
        Input:
            Nothing.
        Returns:
            PC
        Restrictions:
            None.

    void Genital68KSetFetch(void *fetch, GENITAL68K_INT32 type);
    void Genital68KSetPCFetch(void *pcfetch, GENITAL68K_INT32 type);
    void Genital68KSetReadByte(void *read_byte, GENITAL68K_INT32 type);
    void Genital68KSetReadWord(void *read_word, GENITAL68K_INT32 type);
    void Genital68KSetReadLong(void *read_long, GENITAL68K_INT32 type);
    void Genital68KSetWriteByte(void *write_byte, GENITAL68K_INT32 type);
    void Genital68KSetWriteWord(void *write_word, GENITAL68K_INT32 type);
    void Genital68KSetWriteLong(void *write_long, GENITAL68K_INT32 type);
        These functions will attach memory maps to the internal context.
        If you want to attach memory maps to a context you have created
        (which is not mapped in), you must assign them manually.
        Input:
            Memory map array or function pointer (depending on wether
            Genital68K was configured for memory map arrays or handlers)
            Type: GENITAL68K_SUPERVISOR or GENITAL68K_USER. If you are not
            emulating the distinction, this argument can be set to anything
            and will be ignored.
        Returns:
            Nothing.
        Restrictions:
            If different address spaces for supervisor and user modes are
            being emulated and the "type" argument is unrecognized, the
            behavior is undefined.

    void *Genital68KGetFetch(GENITAL68K_INT32 type);
    void *Genital68KGetPCFetch(GENITAL68K_INT32 type);
    void *Genital68KGetReadByte(GENITAL68K_INT32 type);
    void *Genital68KGetReadWord(GENITAL68K_INT32 type);
    void *Genital68KGetReadLong(GENITAL68K_INT32 type);
    void *Genital68KGetWriteByte(GENITAL68K_INT32 type);
    void *Genital68KGetWriteWord(GENITAL68K_INT32 type);
    void *Genital68KGetWriteLong(GENITAL68K_INT32 type);
        Will return the memory map or function pointers that are associated
        with each type of access.
        Input:
            Type: GENITAL68K_SUPERVISOR or GENITAL68K_USER. If you are not
            emulating the distinction, this argument can be set to anything
            and will be ignored.
        Returns:
            Memory map array or function pointer.
        Restrictions:
            If different address spaces for supervisor and user modes are
            being emulated and the "type" argument is unrecognized, the
            behavior is undefined.

    GENITAL68K_UINT8 *Genital68KFetchPtr(GENITAL68K_UINT32 addr);
        Return a host pointer to the specified address in the current address
        space. Genital68K scans the fetch region and if the address is not
        found, it will return 0. This is useful for disassemblers.
        Input:
            Address.
        Returns:
            Host address.
        Restrictions:
            Only the address space currently being used will be scanned. In
            order to select the supervisor or user address space, you will
            have to modify the privilege mode bit in SR and restore it to its
            original value when finished.         
        
    GENITAL68K_UINT8 Genital68KReadByte(GENITAL68K_UINT32 addr);
    GENITAL68K_UINT16 Genital68KReadWord(GENITAL68K_UINT32 addr);
    GENITAL68K_UINT32 Genital68KReadLong(GENITAL68K_UINT32 addr);
    void Genital68KWriteByte(GENITAL68K_UINT32 addr, GENITAL68K_UINT8 data);
    void Genital68KWriteWord(GENITAL68K_UINT32 addr, GENITAL68K_UINT16 data);
    void Genital68KWriteLong(GENITAL68K_UINT32 addr, GENITAL68K_UINT32 data);
        These functions read/write data from the current Genital68K address
        space. Thus, they can call handlers you have set up. These are
        particularly useful for debuggers. Be careful, the PC (and possibly
        other context data) will be invalid.
        Input:
            Address (and data if writing.)
        Returns:
            Data (or nothing if writing.)
        Restrictions:
            Do not use while Genital68K is running.

    void Genital68KSetContext(struct GENITAL68K_CONTEXT *context);
    void Genital68KGetContext(struct GENITAL68K_CONTEXT *context);
        Map contexts in and out of the internal context using this pair of
        functions. Genital68K operates only on its internal context, so it is
        necessary to copy externally-defined contexts into genital68kcontext_*
        when you want to emulate the processor they define. These functions
        also make adjustments to the addresses contained in fetch, read_byte,
        etc. in order to speed things up -- therefore you cannot access these
        members, or any other context member, while it is mapped in.
        Input:
            Address of context to map in/out.
        Returns:
            Nothing.
        Restrictions:
            Do not use while Genital68K is running.
        
    GENITAL68K_UINT32 Genital68KGetContextSize();
        Returns the size, in bytes, of a Genital68K context. This is useful
        for asserting that your compiler is packing the contexts correctly.
        Input:
            Nothing.
        Returns:
            Size of context in bytes.
        Restrictions:
            None.
        
    void Genital68KClearCycles();
        Clears both "cycles" and "remaining" causing Genital68K to exit early.
        Be careful: a call to Genital68KGetElapsedCycles() after this will
        return 0 or a small number which does not reflect the total amount of
        cycles used since Genital68K was last called to run.
        Input:
            Nothing.
        Returns:
            Nothing.
        Restrictions:
            None.

    void Genital68KFreeTimeSlice();
        Causes Genital68K to stop running early by working some magic on both
        "cycles" and "remaining." Unlike Genital68KClearCycles(), you can get
        the number of cycles executed with Genital68KGetElapsedCycles().
        Input:
            Nothing.
        Returns:
            Nothing.
        Restrictions:
            If called from a handler, Genital68K does not actually stop
            running until the current instruction finishes.

    GENITAL68K_INT32 Genital68KGetElapsedCycles();
        Returns the amount of cycles run.
        Input:
            Nothing.
        Returns:
            Cycles run.
        Restrictions:
            None.
        

---------------------
  6. Hints and Tips
---------------------

For those of you who want to get the most out of Genital68K, this section aims
to provide you with some neat little tricks to try.


6.1 Alternative Identifiers

The default identifier names have nothing preceding them (Genital68KInit(),
genital68kcontext_68000, Genital68KReset(), etc.) However, if the need arises,
you can change the identifier names by adding a string (up to 16 characters)
to the beginning of them.

Use the -id option to emit Genital68K with different identifier names. The
data types and macros will not be changed, GENITAL68K_CONTEXT_68000 will
remain as it is, so will GENITAL68K_OKAY, etc.

You must also use the GENITAL68K_ID() macro defined in GEN68K.H to set the new
identifier names immediately after the header file has been included. For
example, if you want identifiers that start with "foo" you would write:

    #include "gen68k.h"
    GENITAL68K_ID(foo);

You can do this multiple times. If you have linked in 2 copies of Genital68K,
one with identifiers that start with "foo", and another with identifiers
starting with "bar", you would write:

    #include "gen68k.h"
    GENITAL68K_ID(foo);
    GENITAL68K_ID(bar);

With the above example, you would have functions like: fooGenital68KInit(),
barGenital68KInit(), and (if you linked in another copy of Genital68K without
modified identifiers) Genital68KInit().


6.2 Multiple Processors

Emulating multiple processors is fairly simple (unless extremely accurate
timing is required.) You have to set up a context for each processor. You may
not use the internal context as one of them, since it will be overwritten if
you map in the other processor.

    Simplistic Example of Running 2 68000s:
    ---------------------------------------

    struct GENITAL68K_CONTEXT_68000 context[2];

    /* ... */

    for (int i = 0; i < 2; i++)
    {
        Genital68KSetContext(&context[i]);
        Genital68KRun(500);
        Genital68KGetContext(&context[i]);
    }

Since Genital68K is non-reentrant, you cannot multi-thread 2 processors unless
you link in 2 separate builds of Genital68K (with different identifier names,
you can use the -id option for this.)


6.3 Maximizing Speed and Minimizing Size

What better reason to write a CPU emulator in assembly language than speed and
size? To get the most speed and least size (the 2 don't always co-exist) out
of Genital68K, here are a few things you can try:

    1. If you are using memory map arrays, set them up wisely. If you have
       memory regions bordering each other, try turning them into a single
       large region. This not only cuts down the time it takes to scan through
       the map, but lets code flow between the regions. Put the most commonly
       accessed regions at the beginning of the array, and the least commonly
       accessed at the end.
    2. Consider using handlers and not memory map arrays (-handler option.) If
       you can write a fast and clean set of handlers, you can speed things up
       by taking a load of work off of Genital68K's back. Optimize your long-
       word handlers as well. It is perfectly okay to have a long-word handler
       call your word handlers twice and return the combined data, but it is
       faster to write the handlers specifically for long-word accesses. 
    3. Execute code in large time slices. The overhead of Genital68KRun() is
       significant but it can be compensated by spending more time emulating.
       Throw Genital68KSetContext()/Genital68KGetContext() in the mix and the
       gains are even greater.
    4. If possible, use -nobrafetch (the default) instead of -brafetch. The
       branch instructions are used a lot. If -skip does not impact compatib-
       ility, consider using it, too.
    5. If you can get away with sneaking in a 32-bit address bus, do it. The
       68000 and 68010 actuall use a 24-bit address bus, which means that
       Genital68K has to mask off the unused bits when fetching data. The
       overhead of doing this is negligible, but if you can get away with using
       the full 32-bits, go for it.
    6. Don't allow separate address spaces for supervisor and user if you can
       get away with it (with most systems, it isn't needed.) This reduces
       some overhead in some of the instruction handlers and functions.
    7. Link the Genital68K object file close to the object files which call it
       most frequently. The theory behind this is that the processor will be
       able to easily cache in code areas that use each other often. It might
       not always yield any speed increase, but I have observed slightly
       quicker performance when optimizing the link order in Genital.
    8. Strip the program you compile, this will reduce the executable tremend-
       ously. Genital68K leaves behind a lot of symbols and junk.

There is a lot to do on my part. Genital68K features some really poor code,
but usually in uncommon instructions. When/if I have time, I will optimize
what I can, but not all at once.


-----------------------
  7. Additional Notes
-----------------------

This is a collection of miscellaneous notes, points of interest, and errata.


7.1 Change History

May 7, 2001: Version 0.35
    - Output file is now properly closed on exit
    - RTD is no longer emitted as a 68000 instruction (68010 only)
    - Initial PC and SP are now read from the instruction fetch memory maps
    - Instructions are emitted in a more optimal order, cache performance
      might be better

April 29, 2001: Version 0.3
    - Fixed a MOVEM bug (example: MOVEM.L (A7)+,A7)
    - Added rudimentary 68010 support
    - "MOVE from SR" is no longer privileged for 68000 processors
    - Rewrote documentation
    - Possibly other minor changes I forgot to list

February 11, 2001: Version 0.22
    - Added a PC-relative read mode (useful in very special circumstances)
    - Removed some unused data
    - Removed sign-extended byte read functions (they were not being used)

January 13, 2001: Version 0.21
    - Fixed Genital68KReadXXX() and Genital68KWriteXXX() functions, they no
      longer trash the PC

January 7, 2001: Version 0.2
    - Slightly modified Genital68KReadXXX() and Genital68KWriteXXX() functions
    - Registers are now saved when Genital68K functions are called
    - Minor optimizations here and there

December 8, 2000: Version 0.12
    - Fixed a bug with register calling conventions and read/write handlers

December 4, 2000: Version 0.11
    - Fixed a bug in Genital68KGetContext() and Genital68KSetContext() which
      corrupted user and supervisor address spaces
    - Corrected a misleading comment in MAKE68K.C and updated the macro refer-
      ence in this document

December 3, 2000: Version 0.1
    - Added user/supervisor address space distinction (optional)
    - Changed address space functions
    - Added a GENITAL68K_NULL macro
    - Fixed some mistakes in this document

November 23, 2000: Version 0.0
    - Initial release


7.2 Un-emulated Features

The following are not emulated:

    Tracing         Genital68K does not emulate trace exceptions.
    Address Errors  Genital68K does not emulate address error exceptions. This
                    usually is unimportant.
    Bus Errors      Bus errors are not emulated.
    Undefined Bits  Undefined bits in the SR are usually kept 0, undefined
                    condition flags in the CCR are actually undefined.
    FC Output Lines The real 68000 and 68010 classify address space accesses
                    as either "User Data", "User Program", "Supervisor Data",
                    "Supervisor Program", or "CPU Space." Genital68K
                    simplifies this by supporting a user address space and a
                    supervisor address space. There is also an option to
                    disable this distinction and use one address space.    
    MOVES           The effects of the alternate function code registers (SFC
                    and DFC) are not emulated. This includes the 68010 MOVES
                    instruction.
    Loop Mode       Loop mode (68010) is not emulated. Perhaps if someone
                    supplies me with very detailed information on how it
                    works, I might consider adding it.
    Stack Frames    Only stack frame 0 is supported. Stack frame 8 (associated
                    with group 0 exceptions: bus and address errors) is never
                    used and if encountered, Genital68KRun() returns a stack
                    frame error. When such an error occurs, the processor
                    state will look as if the problematic RTE instruction had
                    never been executed.
    68010 Timing    For instructions common to both the 68000 and 68010 (most
                    of them), 68000 timing is used.


7.3 Errata

Although I have attempted to fix every bug I came across, there is bound to be
something obscure, or possibly major, left undiscovered. There are a few
unimportant inaccuracies I do know about, but have not bothered to fix yet:

    DIVS, DIVU      Timing is off by up to 10% in worst-case scenarios.
    MULS, MULU      Timing is off by an unknown amount. The multiplication
                    algorithm used by the 68000 and 68010 affects timing in
                    pretty odd ways.
    Timing          Some of the instructions have slightly inacurrate timing,
                    usually because of human error. Timing for exceptions and
                    interrupts is often wrong (but not TOO far off.)
    Dummy Reads     Some instructions (CLR, MOVE from SR, etc.) perform an
                    unnecessary read before writing to memory. This is not
                    emulated. This can affect some systems, but usually is not
                    important.                    
    Exceptions      Priority between interrupts and other exceptions (such as
                    privilege violation, division by 0, TRAP, TRAPV, etc.) is
                    not fully emulated. Priority among interrupts themselves
                    seems to be properly handled, and that is most important.
                    I have not seen any situations where interrupts and other
                    exceptions affect each other.
    
More information on the priority of spurious and uninitialized interrupts as
well as level 7 would be appreciated. I am going off what little the Motorola
manuals say.


7.4 Bibliography

Most of what I know about 680X0 processors comes from the 2 free manuals I
ordered from Motorola. The rest comes from individuals who kindly helped me
and are mentioned in section 8.

    Documents Used:
    ---------------
    - "Programmer's Reference Manual" by Motorola (M68000PM/AD REV 1)
    - "M68000 8-/16-/32-Bit Microprocessor User's Manual Ninth Edition" by
      Motorola (M68000UM/AD REV 8)


---------------------
  8. Special Thanks
---------------------

Many thanks go out to those who helped me out with Genital68K and contributed
to the project in any form.

    - Neil Bradley
    - Victor Moya
    - Dynarec Mailing List: M.I.K.e, Neil Griffiths, Gwenole, etc.
    - Quintesson
    - Steve Snake
    - Tim Meekins
    - Kuwanger
    - Charles MacDonald
    - Stephane Dallongeville
    - Eli Dayan
    - Neill Corlett
    - Pete Dabbs
    - ElSemi

And, of course, thank YOU! Remember, comments, suggestions, and contributions
are more than welcome, so get in touch with me. See you next time!
