Skip to content

hazzaclark/lib68k

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

lib68k

Motorola 680x0 Standalone Emulation Library

image

Motive:

The motive behind this repository is to provide a surrogate means of aiding in relevant Motorola 68000 developments.

Created using ANSI C99 standard, this project aims to promote an ease of use means of creating a library that emulates the likeness of these microprocessors

Features:

  • Accurate CPU Emulation
  • Verbose Execution Model (precomputed Jump Table using Function Pointer)
  • Flexible Memory Mapper Scheme (RAM, ROM, IO and Vectors)
  • auto-disable for options
  • Specialised Interrupt Handler and Vector Exception Table
  • Fully expandable Macros definitions (for pre-processing functions at compile time)

Usage:

git clone this repository

make clean

make

the following output will vary depending on system:

Windows:

lib68k.a

UNIX:

lib68k.so

the makefile in question is universal, allowing for ease of use compiling on other systems

Running the samples (w/ simulator)

In my experience, I have found that compiling with clownassembler works the best - for it's ease of use means of being able to provide input and output as well as providing in depth and concise warnings and error messages.

Follow the repository's instructions on how to work with that, or alternatively, use a 68K Assembler of your choosing

Another example is showcasing the Memory Read and Writes in accordance with the design of the struct which encompasses said logic

Motorola 68K-specific Big Endian Reads, accounting for Endianness Swap

image

Running the simulator with imm.bin

image

Auto-disable functionality:

For the sake of simplicity when it comes to the debugging utilities, I have implemented the functionality to turn HOOKS on and off

Simply use the oscillating macros of M68K_OPT_ON or M68K_OPT_OFF should you ever need more or less debugging information

 	#define 	M68K_JUMP_HOOK 		M68K_OPT_ON
	#define		M68K_RTS_HOOK		M68K_OPT_ON
	#define		M68K_RESET_HOOK		M68K_OPT_ON

	 // TURN THE EQUALISER TO ON AND OFF

	#if M68K_JUMP_HOOK == M68K_OPT_ON
    #define M68K_BASE_JUMP_HOOK(ADDR, FROM_ADDR) \
        do { \
            printf("[JUMP TRACE] TO: 0x%08X FROM: 0x%08X\n", (ADDR), (FROM_ADDR)); \
        } while(0)
	#endif

	#if M68K_RTS_HOOK == M68K_OPT_ON
    #define M68K_BASE_RTS_HOOK(FROM_ADDR) \
        do { \
            printf("[RTS] 0x%04X\n", (FROM_ADDR)); \
        } while(0)
	#else
    	#define M68K_BASE_RTS_HOOK(FROM_ADDR) ((void)0)
	#endif

	#if M68K_RESET_HOOK == M68K_OPT_ON
    #define M68K_BASE_RES_HOOK(T0, T1, PC, SP) \
        do { \
            printf("RETURNED WITH TRACE LEVEL (T0: %d, T1: %d) -> CURRENT PC: %d -> CURRENT SP: 0x%04X\n", \
                  (T0), (T1), (PC), (SP)); \
        } while(0)
#else
    #define M68K_BASE_RES_HOOK(T0, T1, PC, SP) ((void)0)
#endif

Execution Flow and reading Instructions in Memory

One of the intrinsic features encompassing lib68k is the ability to precompute the Opcodes at compile-time.

This is achieved through the M68K_BUILD_OPCODE_TABLE function, which generates a static array of all of the presupposed elements within the table.

From there, the pointer encompassing the generation of the Opcode Handler Table itself is linked to a function pointer.

The function pointer in question doesn't account for an end-all-be-all design approach in accessing Opcodes. Since everything is mapped by the struct irrespective of the context, at runtime it will mould to suit whichever circumstance is required of the Opcode being fetched in execution, (size, type, EA mode, IMM value, etc).

OSTRUCT = M68K_OPCODE_HANDLER_TABLE;
while (OSTRUCT->HANDLER != NULL)
{
        #if USE_OPCODE_DEBUG == M68K_OPT_ON

        printf("PROCESSING OPCODE: MASK = 0x%04X, MATCH = 0x%04X, HANDLER = %p\n",
               OSTRUCT->MASK, OSTRUCT->MATCH, (void*)&OSTRUCT->HANDLER);

        #endif

        for (INDEX = 0; INDEX < 0x10000; INDEX++)
        {
            // IF THE CORRESPONDING OPCODE MASK FROM THE TABLE 
            // MATCHES HOW IT APPEARS IN TRAD 68K, USE THE CORRESPONDING AMOUNT OF CYCLES

            if ((INDEX & OSTRUCT->MASK) == OSTRUCT->MATCH)
            {
                M68K_OPCODE_JUMP_TABLE[INDEX] = OSTRUCT->HANDLER;
                CYCLE_RANGE[INDEX] = OSTRUCT->CYCLES;               
            }
        }

        OSTRUCT++;
    }
// 68K.c - FROM M68K_EXEC

// READ THE CURRENTLY AVAILABLE INSTRUCTION INTO THE INDEX REGISTER
M68K_REG_IR = M68K_READ_MEMORY_16(M68K_REG_PC);

// MAP THAT NEWLY GATHERED OPCODE FROM THE IR INTO THE FUNCTION POINTER
M68K_OPCODE_JUMP_TABLE[M68K_REG_IR]();

// MANUALLY ADVANCE THE PC TO PROPERLY READ THE NEXT (PC advances are bound to change based on EA mode in Opcode def)
M68K_REG_PC += 2;

Sources:

Motorola 680x0 Programmer Manual

Motorola 680x0 User Manual

68000 Memory Map

68K General-purpose manual

68000 ISA

lib68k_mem

68K Instruction Timings

imHex (for being a brilliant Hex Editor)

More 68K Instruction Timings

About

Motorola 680x0 Standalone Emulation Library

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •