From 129eb5210bd8bb5175c6b8b2dac48d7a1e9ed069 Mon Sep 17 00:00:00 2001 From: orbea Date: Fri, 21 Jan 2022 18:04:47 -0800 Subject: [PATCH] fame: Add html file with terms of use Source: http://www.emu-france.com/emulateurs/7-processeurs/82-680x0/2311-fame/ Fixes https://github.com/notaz/picodrive/issues/132 --- cpu/fame/fame.html | 1128 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1128 insertions(+) create mode 100644 cpu/fame/fame.html diff --git a/cpu/fame/fame.html b/cpu/fame/fame.html new file mode 100644 index 000000000..9d9ebfee8 --- /dev/null +++ b/cpu/fame/fame.html @@ -0,0 +1,1128 @@ + + + +FAME Fast and Accurate Morolora 68000 Emulation Library + + + + +
+
F.A.M.E.
+ Fast and Accurate Morolora 68000 Emulation Library

+ Copyright (c) 2002-2005 Oscar Orallo Peláez / Daniel Lancha García. All rights + reserved.

+ March 14th, 2006
+
+
+

Table of Contents

+
+
+
+

0. Introduction
+ 1. Terms of Use
+ 2. Version History
+
3. What is emulated
+ 4. Using the emulation library
+     4.1. Data structure
+         4.1.1. + CPU context
+         4.1.2. + Memory map definition example
+     4.2. Memory handling
+     4.3. Running the CPU
+ 5. Interrupts and exceptions
+
    5.1. Interrupt + acknowledge
+     5.2. Customizing + processing (HLE)
+     5.3. IRQ lowering
+ 6. Function Reference
+     6.1. General Purpose + Functions
+     6.2. Hardware interrupt + handling functions
+     6.3. CPU context handling + functions
+     6.4. Timing functions
+ 7. Multi-CPU systems
+ 8. Helpful tips
+ 9. Troubleshooting
+ 10. Known bugs
+ 11. Special thanks

+
+
+
+ + + + +
+ 0. Introduction
+

This is the documentation for FAME library, please read it.

+

FAME is an extremely fast and accurate Motorola 68000 Emulation Library. + It is currently available for Intel x86-based systems (80386 or better processor) + and SH-4 based systems.

+

The x86 version was designed to work under any win32 development environment + such as Microsoft Visual Basic, Microsoft Visual C++, Borland Delphi or Borland + C++ Builder.

+

The SH-4 version was specially designed for the Dreamcast videogame console + but it can be used in any SH-4 based system.

+

This manual tries to be a guide to get the emulation library working in your + development environment. I hope you find it useful. If you use FAME in your + project I would like to hear your opinion about it.

+

The package contains one example (C++ program) to show how the library should + be called and used. It was compiled successfully in Microsoft Visual C++ 6.0 + SP5, Borland C++ Builder 5/6 and Borland C++ Compiler 5.5.

+

If you have any questions about how it works in your favorite compiler send + me an email. I'd like to help you with FAME.
+ If you find any bug in FAME, it would be nice that you inform me about that via + email. Any feedback, comments + and suggestions will also be appreciated.

+

How to contact Oscar Orallo:

+
+

E-mail:      oscar@m68k.com
+ Web site:  http://www.m68k.com/fame

+
+

FAME Distribution: http://www.m68k.com/fame/fame.zip + (latest)
+FAME Development Package: http://www.m68k.com/fame/famedev.zip (latest)

+

Here we go folks, have fun :)

+

 

+ + + + +
 1. + Terms of use
+

FAME is a development package that contains the following files:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileDescription
/x86/win32/fame.dllMicrosoft win32 dinamic link library
/x86/linux/libfame.ax86 static ELF library
/x86/cygwin/libfame.ax86 static win32 library
/sh4/libfame.aSH-4 static ELF library
/delphi/fame.pasDelphi unit
/doc/fame.htmlDocumentation file
/example/main.cC source code example
/example/makefile.cygwinCygwin example makefile
/example/makefile.dcDreamcast example makefile
/example/makefile.linuxLinux example makefile
/example/romdisk/bubble.binMotorola 68000 binary code file
/lib/bc/fame.libBorland C++ 32-bit import library
/lib/vc/fame.expMicrosoft Visual C++ 32-bit export file
/include/fame.hC/C++ header file
+


+ FAME may be distributed freely in unmodified form, as long as this document +file is included.

+

Nothing may be charged for this library. If you want to use it in a shareware + or commercial application, contact me.

+

The author will not be held liable for damages. FAME comes with absolutely + NO WARRANTY. Anyway i will try to help you with any problem you have using FAME.

+

If you do not agree with all of these terms, please remove FAME from your computer.

+

You are encouraged to contact the author if you wish to use FAME in a commercial + product (to negotiate licensing).

+

Any program which uses FAME must include in its documentation or in the program + itself the following credit text:

+

FAME Motorola 68000 Emulation Library by Oscar Orallo (oscar@m68k.com)

+

 

+ + + + +
 2. + Version History
+
+ + + + + + + + + +
Intel® + 80386 CISC engine
Super H® SH-4 RISC + engine

Version 2.0a (14th, march, 2006)

+

- Stupid bug fixed in IRQ management (thanks Martin Kresse).
+ - Accurate DIV timing implemented (thanks Jorge Cwik).
+ - Overflow detection fixed in signed DIV instruction.
+ - Added makefiles for linux and cygwin environments.

+

Version 2.0 (11th, january, 2006)

+

- set_irq_type API function removed. IRQs will be automatically lowered once it was attended.
+ - Many flag calculations fixed.
+ - Some minor tweaks.

+

Version 1.23 (5th April, + 2005)

+

- Timing fixed in MOVEM instructions.

+

Version 1.22 (7th March, 2005)

+

- Fixed a stupid bug in fetch function.

+

Version 1.21 (19th February, 2005)

+

- set_irq_type function changed for flexible use.
+ - Pointer to data structure parameter removed from memory handlers to + increase throughtput.

+

Version 1.2 (17th December, 2004)

+

- Fixed the PC base calculation for fetch memory regions beyond the first + allocated area.
+ - Fixed a tiny error in the status register masking. Several instructions + could generate an invalid value.
+ - Fixed JSR instruction when jumping to a fetch bank different to the + current one.
+ - Tiny error fixed in interrupt acknowledge function parameter.
+ - Fixed the set_context function when setting status register.
+ - Fixed the PC restoring in HLE feature.
+ - Fixed DIVS instruction operation.

+

Version 1.1 (7th October, 2004)

+

- New static ELF library available.
+ - Interrupt acknowledge calling bug fixed.
+ - Custom exception processing (HLE) feature added.
+ - Some little changes in CPU context (register ordering).
+ - Flag N calculation in CHK instruction fixed.
+ - Some little code tweaks.
+ - New sections added to this document.
+ - Some defines added to header file.
+ - Some return values have been changed.
+ - Set/get context functions simplified. Some changes have been applied. +

+

Version 1.0g (2nd August, 2004)

+

- Speed emulation increased once more. The fetch/decode/execute loop + has been inlined.
+ - Some API functions added: add_cycles and release_cycles.
+ - Memory handling section added to this document (thanks Richard Hollstein + for requesting it).
+ - Faster memory access (both program code and data). Memory regions must + be 4 KB aligned now.
+ - Overhead reduced in emulate function calls (entry/exit code + optimized).
+ - Interrupt acknowledge function added.
+ - Some code tweaks here and there.
+ - Static library for Borland C++ compilers added to the package.
+ - DLL file size reduced: internal compression (UPX).
+ - Fixed a bug in STOP instruction: the processor started up after an interrupt + request even if its interrupt level was not higher than current PPL.
+ - Ver little optimization in branch instructions.
+

+

Version 1.0f (23th February, 2003)

+

- API functions added: get_register and set_register + to retrieve and set register values.
+ - Small optimizations for improved speed.
+ - CPU context modified: execinfo added for more complete CPU state handling + support.
+ - LIB file added to package to support implicit linking :).
+ - Changes in documentation.
+ - C header file (fame.h) and Delphi unit (fame.pas) modified.
+

+

Version 1.0e (18th February, 2003)

+

- Emulation core speed increased lightly (faster entry/exit code). Now + the library is pretty fast.
+ - Some changes in function and variable naming (odometer changed to cycles_counter).
+

+

Version 1.0d (20th December, 2002)

+

- Fetch function speed incremented a bit.
+ - Fixed memory boundary for byte data accesses.
+

+

Version 1.0c (27th August, 2002)

+

- Fixed a stupid bug in group 0 exceptions management.
+

+

Version 1.0b (16th August, 2002)

+

- Many errors corrected in documentation about memory mapping.
+ - The function fetch has now capability to access to the data + address space.

+


+ Version 1.0a (24th July, 2002)

+

- First public release.

Version 2.0a (14th, march, 2006)

+

- Timing fixed for DIV and signed MUL instructions.
+ - Improved overflow detection in signed DIV instruction.
+ - Added makefile for Dreamcast system (requires KOS).

+

Version 2.0 (11th, january, 2006)

+

- Tons of bugs fixed (thanks Chui).
+ - Accurate DIV timing implemented (thanks Jorge Cwik).
+ - set_irq_type API function removed. IRQs will be automatically lowered once it was attended.
+ - Great speed improvements.

+

Version 0.04 (5th April, 2005)

+

- Lightweighted entry/exit code.
+ - Fixed sign/zero flag calculation when moving long data from memory to + memory.
+ - Privilege violation exception fixed.
+ - Faster interrupt/exception management.
+ - Timing fixed in MOVEM instructions.

+

Version 0.03 (7th March, 2005)

+

- Sign flag calculation in inmediate logical instruction fixed.
+ - Carry flag calculation in NEG instruction fixed.
+ - Overflow flag in operations with X flag fixed.
+ - Fixed CPU state stop bit.
+ - Speed up by about 20%.
+ - Tiny tweaks here and there and everywhere.

+

Version 0.02 (19th February, 2005)

+

- First beta release.
+ - set_irq_type function changed for flexible use.
+ - Greatly improved internal memory management.
+ - Pointer to data structure parameter removed from memory handlers to + increase throughtput.
+ - DIV/DIVS instructions fixed.
+ - ABCD/SBCD adjusted result fixed.
+ - MOVEM (control addressing mode) instruction fixed.
+ - BTST with memory addressing mode fixed.
+ - Fixed Z flag calculation in NEGX instruction.
+ - Fixed TAS instruction.
+ - Fixed RESET instruction (external handler calling).
+ - Fixed ILLEGAL instruction (exception generation).
+ - Quick ADD to address register fixed.
+ - EXG instruction fixed.
+ - V flag calculation fixed in ASL instruction.
+ - Some tiny tweaks & improvements.

+

Version 0.01b (17th December, 2004)

+

- Memory map cache generation fixed.
+ - Fixed the PC restoring in HLE feature.
+ - Many opcodes fixed.
+ - Lots of bugs fixed.

+

Version 0.01a (7th October, 2004)

+

- First public release. Alpha development state!

+

 

+ + + + +
 3. + What is emulated
+

This library emulates the Motorola 68000 microprocessor. The main emulation + features are the following:

+ +

 

+ + + +
 4. + Using the emulation library
+

4.1. Data structure

+

The data structures used in the emulation core is defined in the C file header + fame.h. In this file you will get all the data structures needed to use the + library.
+
+ If you cannot use this file because you are not using a C/C++ compliant compiler + you have to define this structures by yourself in your code.

+

Here I describe these data structures.

+
+

struct M68K_PROGRAM
+ {
+     unsigned low_addr;
+     unsigned high_addr;
+     unsigned offset;
+ }

+
+

This structure defines the memory regions for 68000 program code. The fields + low_addr and high_addr are 32-bit values used for determine + the low and high address of the memory block in the 68000 memory map.

+

The last field is a 32-bit pointer to the data of the memory region. The data + pointed by it must be allocated in native (Motorola) format. If not, the data + will be fetched incorrectly. Make sure of this fact.

+
+

struct M68K_DATA
+ {
+     unsigned low_addr;
+     unsigned high_addr;
+     void *mem_handler;
+     void *data;
+ }

+
+

This one is used for 68000 data code. This structure has an appearance very + similar to the last one but has a diference in the way you can give the control + of the memory to FAME. The pointer called mem_handler is a function + pointer. This pointer is used for memory management, so when you want to take + control in the reading/writing of a memory region, you have to set this pointer + to the appropriate value. If you do not want to use this funcionality you have + to set this pointer to NULL and set data pointing to the data itself. + The different ways to perform memory handling will be described with more detail + in memory handling section.

+

4.1.1. CPU + context

+
+

struct M68K_CONTEXT
+ {
+     struct M68K_PROGRAM *fetch;
+     struct M68K_DATA *read_byte;
+     struct M68K_DATA *read_word;
+     struct M68K_DATA *write_byte;
+     struct M68K_DATA *write_word;
+     struct M68K_PROGRAM *sv_fetch;
+     struct M68K_DATA *sv_read_byte;
+     struct M68K_DATA *sv_read_word;
+     struct M68K_DATA *sv_write_byte;
+     struct M68K_DATA *sv_write_word;
+     struct M68K_PROGRAM *user_fetch;
+     struct M68K_DATA *user_read_byte;
+     struct M68K_DATA *user_read_word;
+     struct M68K_DATA *user_write_byte;
+     struct M68K_DATA *user_write_word;
+     void (*reset_handler)(void);

+     void (*iack_handler)(unsigned level);
+     unsigned *icust_handler;
+     unsigned dreg[8];
+     unsigned areg[8];
+     unsigned asp;
+     unsigned pc;
+     unsigned cycles_counter;
+     unsigned char interrupts[8];
+     unsigned short sr;
+     unsigned short execinfo;
+ }

+
+

This structure defines a CPU context. You have to declare a variable of this + type. It contains all information related with the context of the CPU.

+

You have to set pointer values of sv* + which defines the supervisor memory map. In order to get the CPU into user mode, + set the user* + pointers.

+

The pointer reset_handler is called when the RESET instruction is + executed. In this way, you can reset all external devices in the calling to + this function. If you do not want to use this feature remember to set this pointer + to NULL.

+

The pointer iack_handler is called whenever a hardware interrupt is + handled by the CPU. This feature will be covered later in Interrupts + and exceptions section.

+

The pointer icust_handler is intented to point to an array of function + pointers to handle customized interrupt/exception processing (known as High + Level Emulation or HLE for short). See Interrupts and + exceptions section to set up this feature.

+

The rest of the structure is managed by FAME so you can read it in execution + time to retrieve information about the CPU.

+

Here I describe some interesting fields for the 68000 programmer:

+
+

- dreg[8] + holds the eight data registers in order (d0 - d7).
+ - areg[8] + holds the eight address registers in order (a0 - a7).
+ - pc + is the current PC address.
+ - asp + stands for Alternative Stack Pointer. It is used to store the not + currently used stack pointer. In supervisor mode, asp is the user stack pointer, + in user mode it is the supervisor stack pointer.
+ - cycles_counter + holds the number of cycles executed so far.
+ - interrupts + is an array that contains information about interrupts.
+ - sr + is the status register.

+
+

4.1.2 Memory map definition + example

+

As an example of an address space definition, consider the following simple + memory map:

+ +

This is the structure for the program address space. I will suppose that ROM, + RAM-1 and RAM-2 contains program code.

+
+

struct M68K_PROGRAM prg_fetch[] + = {
+     {0x000000, 0x01FFFF, (unsigned)rom},
+     {0x300000, 0x407FFF, (unsigned)ram1 - 0x300000},
+     {0x500000, 0x500FFF, (unsigned)ram2 - 0x500000},
+     {-1, -1, NULL}
+ }

+
+

Note that the last entry must be {-1, + -1, NULL}.

+

Now, I will set up the data address space. In this case, I will suppose that + all memory areas will be accesed and that RAM-3 is accessed by the routine mem_access. + To do this, you will have to set up the following:

+

- One structure for read byte operations:

+
+

struct M68K_DATA data_rb[] + = {
+     {0x000000, 0x01FFFF, NULL, rom},
+     {0x300000, 0x407FFF, NULL, ram1 - 0x300000},
+     {0x500000, 0x507FFF, NULL, ram2 - 0x500000},
+     {0x600000, 0x601FFF, mem_access, NULL},
+     {0x800000, 0x80AFFF, NULL, ram4 - 0x800000},
+     {-1, -1, NULL, NULL}
+ }

+
+

- One structure for write byte operations:

+
+

struct M68K_DATA data_wb[] + = {
+     {0x000000, 0x01FFFF, NULL, rom},
+     {0x300000, 0x407FFF, NULL, ram1 - 0x300000},
+     {0x500000, 0x507FFF, NULL, ram2 - 0x500000},
+     {0x600000, 0x601FFF, mem_access, NULL},
+     {0x800000, 0x80AFFF, NULL, ram4 - 0x800000},
+     {-1, -1, NULL, NULL}
+ }

+
+

- One structure for read word operations:

+
+

struct M68K_DATA data_rw[] + = {
+     {0x000000, 0x01FFFF, NULL, rom},
+     {0x300000, 0x407FFF, NULL, ram1 - 0x300000},
+     {0x500000, 0x507FFF, NULL, ram2 - 0x500000},
+     {0x600000, 0x601FFF, mem_access, NULL},
+     {0x800000, 0x80AFFF, NULL, ram4 - 0x800000},
+     {-1, -1, NULL, NULL}
+ }

+
+

- One structure for write word operations:

+
+

struct M68K_DATA data_ww[] + = {
+     {0x000000, 0x01FFFF, NULL, rom},
+     {0x300000, 0x407FFF, NULL, ram1 - 0x300000},
+     {0x500000, 0x507FFF, NULL, ram2 - 0x500000},
+     {0x600000, 0x601FFF, mem_access, NULL},
+     {0x800000, 0x80AFFF, NULL, ram4 - 0x800000},
+     {-1, -1, NULL, NULL}
+ }

+
+

In the example, the routine used for access to ram3 area is the same in all + the structures defined but it could be different.

+

And now the last step is to fill the CPU context with the defined address spaces. + This is accomplished in the following way:

+
+

struct M68K_CONTEXT cpu_contxt;

+

cpu_contxt.sv_fetch = prg_fetch;
+ cpu_contxt.user_fetch = prg_fetch;

+

cpu_contxt.sv_read_byte + = data_rb;
+ cpu_contxt.user_read_byte = data_rb;
+ cpu_contxt.sv_read_word = data_rw;
+ cpu_contxt.user_read_word = data_rw;
+ cpu_contxt.sv_write_byte = data_wb;
+ cpu_contxt.user_write_byte = data_wb;
+ cpu_contxt.sv_write_word = data_ww;
+ cpu_contxt.user_write_word = data_ww;

+
+

Note that the memory address spaces for supervisor and user are the same. This + is very common but remember they could be different.

+

And that is all.
+

+

4.2. Memory handling

+

The emulation library provides two ways to perform the access to the memory + map: built-in and custom.

+

The built-in memory handling is ideal to get the maximun speed to the memory + map but at the cost of less control. To use it you have to set data + pointing to the beginning of the native memory region and set mem_handler + to NULL.

+
+

struct M68K_DATA
+ {
+     unsigned low_addr;
+     unsigned high_addr;
+     void *mem_handler;
+     void *data;
+ }

+
+

The custom memory handling gives you total control over memory accesses but + its use could create a bottleneck in the emulated system if it is used inappropriately. + To use this feature you have to set up mem_handler pointer to the handling + function. That function will be called whenever a memory access is done.
+ There is a restriction in the definition of a memory region: it must be 4 + KB aligned. So it must start on 0XXX000h and end on 0YYYFFFh.

+

Memory handling functions have the following structure:

+

int  read_xxxx (int address);
+ void write_xxxx(int address, int data);

+

where xxxx stands for byte, word or long depending on data size, + address is the memory address accessed and data is the data itself.

+

Using memory handling functions might be a good way to customize emulated memory + space. You have to read/write data in the way FAME expects. This process could + become confusing. To avoid undesired problems in this point, i have written + some simple routines to make your life easier:

+
+

int readbyte(int address)
+ {
+     return ram[address^1];
+ }

+
+ int readword(int address)
+ {
+     return ((unsigned short *)ram)[address>>1]; +
+ }
+

+ void writebyte(int address, + int data)
+ {
+     ram[address^1] = data & 0xFF;
+ }

+
+ void writeword(int address, + int data)
+ {
+     ((unsigned short *)ram)[address>>1] = data & + 0xFFFF;
+ }

+
+

I am considering you have your emulated memory region (pointed by ram here) + in native endian format (this is, big endian for the 68000 processor). Note + the required endianess switch in the byte accesses, since we are reading in + a little endian machine (x86 and SH4 processors).

+


+ 4.3. Running the CPU

+

In order to get the 68000 CPU running, you have to do the following steps:

+
+

1. Initialize the emulation library. Call m68k_init() + to perform this task.
+ 2. Set up the memory map (see section 4.1.2).
+ 3. Reset the processor calling the m68k_reset() + function.
+ 4. Execute code calling m68k_emulate(n) + function where the parameter n means the number of clock cycles to execute.

+
+

Note: See Function Reference section + for more information about how API functions work.

+

 

+ + + + +
 5. + Interrupts and exceptions
+

The library currently emulates the group 0 exceptions (address + error and bus error), group 1 exceptions (trace mode, external + interrupts, illegal opcode and privilege violation) and group 2 exceptions.

+

The reset exception is not emulated. This is due to performance + facts. If this exception was emulated, the performance of the library would + fall notably. If you need this exception be emulated, contact me.

+

Hardware interrupts can be raised at any time, but it will be attended only in the entry code of the emulate function. To manage interrupts, please refer to the section Function Reference bellow.

+

If you have any doubt about how these events work, I recommend you to take a look at M68000 Microprocessors User's Manual (english) or at the book Sistemas Digitales (spanish).

+

5.1. Interrupt + acknowledge

+

Sometimes could be useful to be warned when a hardware interrupt is being attended. + This feature is frequently called interrupt acknowledging and allows + you to take specific actions when an interrupt is handled, signaling a device + to lower the interrupt request, for example.
+ This function accepts one parameter, the interrupt level, and returns no value.

+
+

void iackhandler(unsigned + int_level);

+
+

Once you have defined your function, set up the CPU context:

+
+

struct M68K_CONTEXT cpu_contxt;

+

cpu_contxt.iack_handler + = iackhandler;
+ m68k_set_context(&cpu_contxt);

+
+

If you do not need this feature, set this pointer to NULL to avoid undesired + results.

+

5.2. + Customizing processing (HLE)

+

Sometimes it is needed to trap an exception to perform some native tasks overriding + target system tasks (system BIOS calls, for example).

+

To customize interrupt and exception processing use icusthandler table + pointer. This pointer must point to a table of a total of 256 function pointers, + each one handling each vector exception presented in the 68000 system starting + from address $000000. The index of the table is the vector number.

+

The handling function accepts one parameter, the vector exception number, and + returns no value.

+
+

void icusthandler(unsigned + vector);

+
+

The array of pointers could be used in this fashion:

+
+

/* Function to customize + CHK exception */
+ void chk_handler(unsigned vector)
+ {
+     . . .
+     (some actions)
+     . . .
+ }

+

unsigned fpa[256];               /* + Function Pointer Array declaration */
+ struct M68K_CONTEXT
+ cpu_context;
+
+ fpa[6] = chk_handler;            /* + Customizing CHK exception */
+ cpu_context.icust_handler = fpa;  /* Setting up function pointers */

+
+

Take in account the + following when you use this feature:

+ +

If you do not need this feature, set this pointer to NULL to avoid undesired + results.

+

5.3. IRQ lowering

+

Every IRQ will be automatically lowered once it has been attended. User selectable IRQ lowering type has been removed.

+

 

+ + + + +
 6. + Function Reference
+

This is a brief description of the library functions.

+ +


+ Remember that this is a brief overview. If you do not find answers to your questions, + contact me.

+


+ 6.1. General Purpose Functions
+

+- void m68k_init (void) +
+

This function initialize the emulation library. Must be called before any other + function library.
+

+- unsigned m68k_reset (void) +
+

Resets the CPU. You must set up the memory map before call this function.

+

Return values:

+
+

M68K_OK (0): Success.
+ M68K_RUNNING (1): The function failures because the CPU is + running. Stop the CPU first.
+ M68K_NO_SUP_ADDR_SPACE (2): The CPU could not be resetted + because there is no supervisor memory map for opcode fetching.
+

+
+- void m68k_emulate (int n) +
+

Starts the emulation and executes n clock cycles. This is the function you + have to call to execute 68000's code. The number of elapsed CPU cycles is the + lowest number equal or greater than n.

+


+- unsigned m68k_get_pc (void)

+
+

Returns the current PC address. The value returned by this function does not + have to be equal to the beginning of an instruction.
+

+- unsigned m68k_get_cpu_state (void) +
+

Returns information about the CPU current state. It could be called at any + time to retrieve interesting and useful information about the CPU state.

+

The data returned has the following format:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BitsMeaning
0Internal use. Should be zero.
1Processing a group 0 exception (address error or bus error).
2Double bus fault has happened.
3Trace mode is being processed.
4Processing trace mode exception.
5Processing bus error exception.
6Processing address error exception.
7CPU stopped by the STOP instruction.
8-31Reserved for future use. Should be zero.
+
+

 

+- int m68k_fetch(unsigned address, unsigned memory_space) +
+

Fetches the word pointed by the specified address using the given memory space + from the fetch memory array. The memory space means the following:

+ +

Generally, you will want to fetch a word from a memory map joining two of those + primitives types. For example:

+
+

Supervisor Data Address Space (Supervisor & Data)

+
+

To accomplish this, you have to use a bitwise OR operation:

+
+

M68K_SUP_ADDR_SPACE | M68K_DATA_ADDR_SPACE

+
+

Return value:

+
+

FFFFFFFFh: The address specified is out of bounds in the + given
+ memory space.
+ 0000xxxxh: The fetched word.

+
+


+ 6.2 + Hardware interrupt handling functions
+

+- int m68k_raise_irq (int level, int vector) +
+

This function allows you to generate a hardware interrupt. This event is external + to the CPU and generally activated by an external device. The possible values + for the parameter level are between 1 and 7, both inclusive.

+

For vector the values are the following:

+
+

M68K_AUTOVECTORED_IRQ (-1): Autovectored interrupt.
+ M68K_SPURIOUS_IRQ (-2): Spurious interrupt.
+ 0-255: Vector number.

+
+

Return value:

+
+

M68K_OK (0): Success.
+ M68K_INT_LEVEL_ERROR (-1): The function failures because + there is another interrupt activated at the given level.
+ M68K_INT_INV_PARAMS (-2): Invalid parameter values. The vector + value is not valid or the level is equal to zero.

+
+


+int m68k_lower_irq (int level)

+
+

This function is used to deactivate an interrupt.

+

Return value:

+
+

M68K_OK (0): The interrupt has been deactivated successfully.
+ M68K_IRQ_LEVEL_ERROR (-1): The function failures because + the interrupt is not activated.
+ M68K_IRQ_INV_PARAMS (-2): Invalid interrupt level value.

+
+


+- int m68k_get_irq_vector (int level)

+
+

Calling this function you will get the vector of a generated interrupt at the + given interrupt level.

+

Return value:

+
+

> -1: Requested interrupt vector.
+ M68K_IRQ_LEVEL_ERROR (-1): The function failures because + the interrupt is not activated.
+ M68K_IRQ_INV_PARAMS (-2): Invalid interrupt level.
+

+
+- int m68k_change_irq_vector (int level, int vector) +
+

It allows you to change the vector of a generated interrupt. Remember that + the interrupt must be already activated when you call this function.
+ The possible values for vector are between 0 and 255, both inclusive.

+

Return value:

+
+

M68K_OK (0): Success.
+ M68K_IRQ_LEVEL_ERROR (-1): The interrupt at the given vector + was not activated.
+ M68K_IRQ_INV_PARAMS (-2): Invalid interrupt vector value.

+
+


+ 6.3. + CPU context handling functions
+

+

These functions are intented for handling the CPU context.
+

+- int m68k_get_context_size (void) +
+

Returns the size in bytes of the CPU context.
+

+- void m68k_get_context (void *context) +
+

Fills the context pointed by the pointer with the current CPU context. You + must deserve memory space in order to allocate the CPU context.
+

+- void m68k_set_context (void *context) +
+

Allows you to set up the CPU context. The parameter is a pointer to the context + structure.
+

+- int m68k_get_register (m68k_register reg) +
+

Returns the value of the specified register. If the value of the reg parameter + is not valid, the function will return -1.

+

Note that the value returned by the function when the register specified is + not valid (-1) is a valid 32-bit register value. This may be cause for concern.
+

+- int m68k_set_register (m68k_register reg, unsigned value) +
+

Sets the value of the specified register.

+

Return values:

+
+

M68K_OK (0): Success.
+ M68K_INV_REG (-1): The register specified is not valid.

+
+


+ 6.4. Timing functions

+

These functions allows you to control the CPU cycles executed in the emulation. + This way, you can adjust the emulation speed. The cycles_counter + is the variable used in the library to count the CPU cycles. For each calling + to function emulate, the executed CPU cycles are added to cycles_counter.
+

+- unsigned m68k_get_cycles_counter (void) +
+

Returns the current value of the cycles_counter.
+

+- unsigned m68k_trip_cycles_counter (void) +
+

Returns the current value of the cycles_counter variable and resets + it to zero.

+
+- unsigned m68k_control_cycles_counter (int n) +
+

If the parameter n is equal to zero, the function returns the cycles_counter.
+ Otherwise, it returns the cycles_counter resetting it to zero.
+

+- void m68k_release_timeslice (void) +
+

Calling this function you will request the CPU to finish its execution as soon + as possible. The premature exit will be reflected in the cycles_counter.
+

+

- void m68k_add_cycles (int cycles)

+
+

Call this function when you want to increase the clock cycles counting (cycles_counter + variable).
+ This function could be useful when emulating systems equipped with DMA capabilities, + keeping track of how many clock cycles the CPU was frozen by any device doing + a DMA operation.
+

+

- void m68k_release_cycles (int cycles)

+
+

Call this function when you want to decrease the clock cycles counting (cycles_counter + variable).

+

 

+ + + + +
 7. + Multi-CPU systems
+

Emulating multiple 68000 processors is fairly simple. If you want to emulate + more than one 68000 processor, you have to set up a CPU context and a memory + map for each one (see memory map example).

+

For example, you would do this:

+
+

struct M68K_CONTEXT my_contexts[NUMBER_OF_PROCESSORS];

+

for (int i = 0; i < NUMBER_OF_PROCESSORS; + i++)
+ {
+     m68k_set_context(&my_contexts[i]);
+     m68k_emulate(100);
+     m68k_get_context(&my_contexts[i]);
+ }

+
+

Try to compensate the overhead due to the copying of the contexts emulating + the CPUs in large timeslices.

+

FAME is non-reentrant so you cannot multi-thread several processors. If you + need FAME running in this way, contact me.

+

 

+ + + + +
 8. + Helpful tips
+

- It is recommended to use built-in memory handlers as much as possible because + they should be much faster than others coded into high level languages.

+

- Use timeslices as large as possible because this way you will reduce the overhead + produced by the entry and exit code of the library.

+

- Try to avoid context swapping. It will reduce performance notably.

+

- It is a good idea to call the emulate function with a variable + number of cycles instead of a fixed one. Keep track of how many cycles overflowed + from the last call to emulate and subtract them in the next calling:

+
+

#define CPU_TIMESLICE 100

+

cpu_context.cycles_counter = 0;
+ while(!done)
+ {
+     if (cpu_context.cycles_counter < CPU_TIMESLICE)
+     {
+         m68k_emulate(CPU_TIMESLICE + - cpu_context.cycles_counter);
+     }
+     cpu_context.cycles_counter -= CPU_TIMESLICE;
+ }

+
+

- Library routines were designed with accuracy and speed in mind. Use them + as much as possible in order to reach a fast and accurate emulated system.

+

- The object code contains many symbols for program relocation. Strip your executable when you are done.

+

 

+ + + + +
 9. + Troubleshooting
+

This section tries to help you to get the library working correctly. I hope + you find this section useful.

+

- Remember to call init function before any other function library. + It initialize the library setting up the emulator.

+

- You must call reset function before starting the emulation in order + to get the library working appropriately.

+

- Set up your memory map before reset the CPU. The reset function look up + the vector table.

+

- Ensure that the CPU context has been set correctly after the calling to + set_context.

+

- Check if memory maps are well-constructed. Every memory region must be 4 + KB aligned. This is a common pitfall.

+

- Check if your emulated processor is accessing memory correctly specially + when you have to use memory handling functions. Take a look at the Memory + handling section if you are having problems in this point.

+

- Make sure to set reset_handler, iack_handler and icust_handler + to NULL if you are not using these features. It would be a good idea to set + every byte of a new context to zero to avoid any problem.

+

- Remember to set every handler not used in the array of function pointers + (icust_handler) to NULL to avoid undesired results.

+

- Remember to include fame.h in any C module that use FAME. This header + file is subject to change in future versions.

+

- Make sure to instruct your compiler configuration to treat enum types as + 32-bit ints when using m68k_get_register + and m68k_set_register functions.

+

 

+ + + + +
 10. + Known bugs
+

- The bit I/N (specific information about the processor activity) saved on + the supervisor stack when an address or bus error happens is not calculated + and its value is fixed to one (instruction). This tiny detail will be implemented + in future versions if needed.

+

 

+ + + + +
 11. + Special thanks
+

Many thanks go out to those who helped me out with this library or contributed + to the project in any form in no special order.

+

- Chui for his invaluable work to get this thing up into his NeoGeo + emulator (Neo4All) and for helping me to fix loads of errors.
+ - Bart Trzynadlowski (trzynadl@unr.nevada.edu) + for his notes about 68000 undocumented behavior.
+ - Julio César Álvarez Acosta (julio_a_a@yahoo.es) + for his help to build the import library.
+ - Richard Hollstein for let me know that memory handling functions + were not documented in previous releases.
+ - Jorge Cwik for figuring out the algorithm to calculate the exact number of cycles in DIV instructions.
+ - Neill Corlett for his excellent Starscream 680x0 emulation library + which give me a lot of understandings and ideas on CPU emulation.
+ - Stéphane Dallongeville for Gens (probably the best Genesis/Mega + Drive emulator ever programmed) and for giving me his opinion about several + aspects of 68000 emulation.
+ - BlackAura and Ian Micheal for telling me about the high + level emulation (HLE) feature.
+ - Juan Carlos Hernández Martín (jmartin@uax.es) + for his interest in this project.
+ - Antonio García Guerra for his great book Sistemas Digitales.
+ - The creators of the 68000 microprocessor, because without their work nothing + of this might be a reality.
+
+ Thank you too! for your interest in the library. If you have any suggestions, +comments or contributions do not hesitate to get in contact with me.

+

Have a nice day!

+ +