2011-07-12 04:57:12 +00:00
|
|
|
/**
|
|
|
|
** Supermodel
|
|
|
|
** A Sega Model 3 Arcade Emulator.
|
2011-09-14 19:08:43 +00:00
|
|
|
** Copyright 2011 Bart Trzynadlowski, Nik Henson
|
2011-07-12 04:57:12 +00:00
|
|
|
**
|
|
|
|
** This file is part of Supermodel.
|
|
|
|
**
|
|
|
|
** Supermodel is free software: you can redistribute it and/or modify it under
|
|
|
|
** the terms of the GNU General Public License as published by the Free
|
|
|
|
** Software Foundation, either version 3 of the License, or (at your option)
|
|
|
|
** any later version.
|
|
|
|
**
|
|
|
|
** Supermodel is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
** more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU General Public License along
|
|
|
|
** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
**/
|
|
|
|
|
|
|
|
/*
|
2011-07-31 02:37:31 +00:00
|
|
|
* 68K.h
|
2011-07-12 04:57:12 +00:00
|
|
|
*
|
2011-07-31 02:37:31 +00:00
|
|
|
* Header file for 68K CPU interface. Caution: 68K emulator is not thread-safe.
|
2011-07-12 04:57:12 +00:00
|
|
|
*
|
|
|
|
* TO-DO List:
|
|
|
|
* -----------
|
|
|
|
* - Optimize things, perhaps by using FASTCALL
|
|
|
|
*/
|
|
|
|
|
2011-07-31 02:37:31 +00:00
|
|
|
#ifndef INCLUDED_68K_H
|
|
|
|
#define INCLUDED_68K_H
|
2011-07-12 04:57:12 +00:00
|
|
|
|
2011-08-14 23:59:01 +00:00
|
|
|
#include <cstring>
|
2011-07-12 04:57:12 +00:00
|
|
|
#include "Types.h"
|
|
|
|
#include "Musashi/m68k.h"
|
2011-09-12 18:14:49 +00:00
|
|
|
#include "Musashi/m68kctx.h"
|
2011-07-31 02:37:31 +00:00
|
|
|
#include "CPU/Bus.h"
|
2021-11-22 17:15:06 +00:00
|
|
|
#include "BlockFile.h"
|
2011-07-12 04:57:12 +00:00
|
|
|
|
|
|
|
// This doesn't work for now (needs to be added to the prototypes in m68k.h for m68k_read_memory*)
|
|
|
|
//#ifndef FASTCALL
|
|
|
|
#undef FASTCALL
|
|
|
|
#define FASTCALL
|
|
|
|
//#endif
|
|
|
|
|
2011-09-18 22:44:20 +00:00
|
|
|
#ifdef SUPERMODEL_DEBUGGER
|
2018-01-22 18:27:51 +00:00
|
|
|
namespace Debugger {
|
|
|
|
class CMusashi68KDebug;
|
|
|
|
}
|
2011-09-18 22:44:20 +00:00
|
|
|
#endif // SUPERMODEL_DEBUGGER
|
2011-07-12 04:57:12 +00:00
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
Definitions
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
// IRQ callback special return values
|
|
|
|
#define M68K_IRQ_AUTOVECTOR M68K_INT_ACK_AUTOVECTOR // signals an autovectored interrupt
|
|
|
|
#define M68K_IRQ_SPURIOUS M68K_INT_ACK_SPURIOUS // signals a spurious interrupt
|
|
|
|
|
|
|
|
|
2011-07-31 02:37:31 +00:00
|
|
|
/******************************************************************************
|
|
|
|
CPU Context
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* M68KCtx:
|
|
|
|
*
|
|
|
|
* Complete state of a single 68K. Do NOT manipulate these directly. Set the
|
|
|
|
* context and then use the M68K* functions below to attach a bus and IRQ
|
|
|
|
* callback to the active context.
|
|
|
|
*/
|
|
|
|
typedef struct SM68KCtx
|
|
|
|
{
|
|
|
|
public:
|
2011-09-12 18:14:49 +00:00
|
|
|
m68ki_cpu_core musashiCtx; // CPU context
|
2016-04-10 03:42:41 +00:00
|
|
|
IBus *Bus; // memory handlers
|
2011-07-31 02:37:31 +00:00
|
|
|
int (*IRQAck)(int); // IRQ acknowledge callback
|
2011-09-18 22:44:20 +00:00
|
|
|
#ifdef SUPERMODEL_DEBUGGER
|
2018-01-22 18:27:51 +00:00
|
|
|
Debugger::CMusashi68KDebug *Debug; // holds debugger (if attached)
|
2011-09-18 22:44:20 +00:00
|
|
|
#endif // SUPERMODEL_DEBUGGER
|
|
|
|
|
2011-07-31 02:37:31 +00:00
|
|
|
SM68KCtx(void)
|
|
|
|
{
|
|
|
|
Bus = NULL;
|
|
|
|
IRQAck = NULL;
|
2011-09-12 18:14:49 +00:00
|
|
|
memset(&musashiCtx, 0, sizeof(musashiCtx)); // very important! garbage in context at reset can cause very strange bugs
|
2011-09-18 22:44:20 +00:00
|
|
|
#ifdef SUPERMODEL_DEBUGGER
|
|
|
|
Debug = NULL;
|
|
|
|
#endif // SUPERMODEL_DEBUGGER
|
2011-07-31 02:37:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
~SM68KCtx(void)
|
|
|
|
{
|
|
|
|
Bus = NULL;
|
|
|
|
IRQAck = NULL;
|
|
|
|
}
|
2018-01-22 18:27:51 +00:00
|
|
|
} M68KCtx;;
|
2011-07-31 02:37:31 +00:00
|
|
|
|
|
|
|
|
2011-07-12 04:57:12 +00:00
|
|
|
/******************************************************************************
|
|
|
|
68K Interface
|
2011-07-31 02:37:31 +00:00
|
|
|
|
|
|
|
Unless otherwise noted, all functions operate on the active context.
|
2011-07-12 04:57:12 +00:00
|
|
|
******************************************************************************/
|
2011-09-18 22:44:20 +00:00
|
|
|
|
2011-07-12 04:57:12 +00:00
|
|
|
/*
|
2011-09-22 06:11:47 +00:00
|
|
|
* M68KGetARegister(n):
|
2011-07-12 04:57:12 +00:00
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* n Register number (0-7).
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* Register An.
|
|
|
|
*/
|
|
|
|
extern UINT32 M68KGetARegister(int n);
|
|
|
|
|
2011-09-18 22:44:20 +00:00
|
|
|
/*
|
2011-09-22 06:11:47 +00:00
|
|
|
* M68KSetARegister(n, v):
|
2011-09-18 22:44:20 +00:00
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* n Register number (0-7).
|
|
|
|
* v Value to set register An to.
|
|
|
|
*/
|
|
|
|
extern void M68KSetARegister(int n, UINT32 v);
|
|
|
|
|
2011-07-12 04:57:12 +00:00
|
|
|
/*
|
2011-09-22 06:11:47 +00:00
|
|
|
* M68KGetDRegister(n):
|
2011-07-12 04:57:12 +00:00
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* n Register number (0-7).
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* Register Dn.
|
|
|
|
*/
|
2011-09-18 22:44:20 +00:00
|
|
|
extern UINT32 M68KGetDRegister(int n);
|
|
|
|
|
|
|
|
/*
|
2011-09-22 06:11:47 +00:00
|
|
|
* M68KGetDRegister(n, v):
|
2011-09-18 22:44:20 +00:00
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* n Register number (0-7).
|
|
|
|
* v Value to set register Dn to.
|
|
|
|
*/
|
|
|
|
extern void M68KSetDRegister(int n, UINT32 v);
|
2011-07-12 04:57:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* M68KGetPC():
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* Current program counter.
|
|
|
|
*/
|
|
|
|
extern UINT32 M68KGetPC(void);
|
|
|
|
|
2011-08-09 18:36:29 +00:00
|
|
|
/*
|
|
|
|
* M68KSaveState(StateFile, name):
|
|
|
|
*
|
|
|
|
* Saves the CPU state to the block file.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* StateFile Block file.
|
|
|
|
* name Name of block to create (e.g. "Main 68K"), to facilitate
|
|
|
|
* multiple 68K states in the same file.
|
|
|
|
*/
|
|
|
|
extern void M68KSaveState(CBlockFile *StateFile, const char *name);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* M68KLoadState(StateFile, name):
|
|
|
|
*
|
|
|
|
* Loads the CPU state.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* StateFile Block file.
|
|
|
|
* name Name of block to load.
|
|
|
|
*/
|
|
|
|
extern void M68KLoadState(CBlockFile *StateFile, const char *name);
|
|
|
|
|
2011-07-12 04:57:12 +00:00
|
|
|
/*
|
|
|
|
* M68KSetIRQ(irqLevel):
|
|
|
|
*
|
|
|
|
* Sets the interrupt level (IPL2-IPL0 pins).
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* irqLevel The interrupt level (1-7) or 0 to clear the interrupt.
|
|
|
|
*/
|
|
|
|
extern void M68KSetIRQ(int irqLevel);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* M68KRun(numCycles):
|
|
|
|
*
|
|
|
|
* Runs the 68K.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* numCycles Number of cycles to run.
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* Number of cycles executed.
|
|
|
|
*/
|
|
|
|
extern int M68KRun(int numCycles);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* M68KReset():
|
|
|
|
*
|
|
|
|
* Resets the 68K.
|
|
|
|
*/
|
|
|
|
extern void M68KReset(void);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* M68KSetIRQCallback(F):
|
|
|
|
*
|
2011-07-31 02:37:31 +00:00
|
|
|
* Installs an interrupt acknowledge callback for the currently active CPU. The
|
|
|
|
* default behavior is to always assume autovectored interrupts.
|
2011-07-12 04:57:12 +00:00
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* F Callback function.
|
|
|
|
*/
|
|
|
|
extern void M68KSetIRQCallback(int (*F)(int));
|
|
|
|
|
|
|
|
/*
|
2016-04-10 03:42:41 +00:00
|
|
|
* M68KAttachBus(IBus *BusPtr):
|
2011-07-12 04:57:12 +00:00
|
|
|
*
|
2011-07-31 02:37:31 +00:00
|
|
|
* Attaches a bus object to the 68K, which will be used to perform all address
|
|
|
|
* space accesses. The 8, 16, and 32-bit read and write handlers are used.
|
|
|
|
* This must be set up before any 68K-related emulation functions are invoked
|
|
|
|
* or the program will crash!
|
2011-07-12 04:57:12 +00:00
|
|
|
*
|
|
|
|
* Parameters:
|
2011-07-31 02:37:31 +00:00
|
|
|
* BusPtr Pointer to bus object to use for all address space accesses.
|
2011-07-12 04:57:12 +00:00
|
|
|
*/
|
2016-04-10 03:42:41 +00:00
|
|
|
extern void M68KAttachBus(IBus *BusPtr);
|
2011-07-12 04:57:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* M68KInit():
|
|
|
|
*
|
|
|
|
* Initializes the 68K emulator. Must be called once per program session prior
|
2011-07-31 02:37:31 +00:00
|
|
|
* to any 68K emulation functions. A context must be mapped before calling
|
|
|
|
* this.
|
2011-07-12 04:57:12 +00:00
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* Always returns OKAY.
|
|
|
|
*/
|
2011-09-08 06:34:18 +00:00
|
|
|
extern bool M68KInit(void);
|
2011-07-12 04:57:12 +00:00
|
|
|
|
2011-07-31 02:37:31 +00:00
|
|
|
/*
|
|
|
|
* M68KGetContext(M68KCtx *Dest):
|
|
|
|
*
|
|
|
|
* Copies the internal (active) 68K context back to the destination.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* Dest Location to which to copy 68K context.
|
|
|
|
*/
|
|
|
|
extern void M68KGetContext(M68KCtx *Dest);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* M68KSetContext(M68KCtx *Src):
|
|
|
|
*
|
|
|
|
* Sets the specified 68K context by copying it to the internal context.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* Src Location from which to copy 68K context.
|
|
|
|
*/
|
|
|
|
extern void M68KSetContext(M68KCtx *Src);
|
|
|
|
|
2011-09-18 22:44:20 +00:00
|
|
|
#ifdef SUPERMODEL_DEBUGGER
|
|
|
|
#define DBG68K_REG_PC 0
|
|
|
|
#define DBG68K_REG_SR 1
|
|
|
|
#define DBG68K_REG_SP 2
|
|
|
|
#define DBG68K_REG_D0 3
|
|
|
|
#define DBG68K_REG_D1 4
|
|
|
|
#define DBG68K_REG_D2 5
|
|
|
|
#define DBG68K_REG_D3 6
|
|
|
|
#define DBG68K_REG_D4 7
|
|
|
|
#define DBG68K_REG_D5 8
|
|
|
|
#define DBG68K_REG_D6 9
|
|
|
|
#define DBG68K_REG_D7 10
|
|
|
|
#define DBG68K_REG_A0 11
|
|
|
|
#define DBG68K_REG_A1 12
|
|
|
|
#define DBG68K_REG_A2 13
|
|
|
|
#define DBG68K_REG_A3 14
|
|
|
|
#define DBG68K_REG_A4 15
|
|
|
|
#define DBG68K_REG_A5 16
|
|
|
|
#define DBG68K_REG_A6 17
|
|
|
|
#define DBG68K_REG_A7 18
|
|
|
|
|
2011-09-22 06:11:47 +00:00
|
|
|
/*
|
|
|
|
* M68KGetRegister(ctx, reg):
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* ctx Musashi 68K context.
|
|
|
|
* reg Register (use DBG68K_REG_* macros).
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* Register value.
|
|
|
|
*/
|
2011-09-18 22:44:20 +00:00
|
|
|
UINT32 M68KGetRegister(SM68KCtx *ctx, unsigned reg);
|
|
|
|
|
2011-09-22 06:11:47 +00:00
|
|
|
/*
|
|
|
|
* M68KSetRegister(ctx, reg, value):
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* ctx Musashi 68K context.
|
|
|
|
* reg Register (use DBG68K_REG_* macros).
|
|
|
|
* value Vale to write.
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* True if successful, false if register does not exist.
|
|
|
|
*/
|
2011-09-18 22:44:20 +00:00
|
|
|
UINT32 M68KSetRegister(SM68KCtx *ctx, unsigned reg, UINT32 val);
|
|
|
|
#endif // SUPERMODEL_DEBUGGER
|
2011-07-12 04:57:12 +00:00
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
68K Handlers
|
|
|
|
|
|
|
|
Intended for use directly by the 68K core.
|
|
|
|
******************************************************************************/
|
|
|
|
|
2011-09-18 22:44:20 +00:00
|
|
|
|
2011-07-31 02:37:31 +00:00
|
|
|
extern "C" {
|
2011-09-18 22:44:20 +00:00
|
|
|
|
|
|
|
#ifdef SUPERMODEL_DEBUGGER
|
|
|
|
extern void M68KDebugCallback();
|
|
|
|
#endif // SUPERMODEL_DEBUGGER
|
2011-07-31 02:37:31 +00:00
|
|
|
|
2011-07-12 04:57:12 +00:00
|
|
|
/*
|
|
|
|
* M68KIRQCallback(nIRQ):
|
|
|
|
*
|
|
|
|
* Interrupt acknowledge callback. Called when an interrupt is being serviced.
|
|
|
|
* Actually implemented by calling a user-supplied callback.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* nIRQ IRQ level (1-7).
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* The interrupt vector to use, M68K_IRQ_AUTOVECTOR, or
|
|
|
|
* M68K_IRQ_SPURIOUS. If no callback has been installed, the default
|
|
|
|
* callback is used and always returns M68K_IRQ_AUTOVECTOR.
|
|
|
|
*/
|
|
|
|
extern int M68KIRQCallback(int nIRQ);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* M68KFetch8(a):
|
|
|
|
* M68KFetch16(a):
|
|
|
|
* M68KFetch32(a):
|
|
|
|
*
|
|
|
|
* Read data from the program address space.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* a Address to read from.
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* The 8, 16, or 32-bit value read.
|
|
|
|
*/
|
|
|
|
unsigned int FASTCALL M68KFetch8(unsigned int a);
|
|
|
|
unsigned int FASTCALL M68KFetch16(unsigned int a);
|
|
|
|
unsigned int FASTCALL M68KFetch32(unsigned int a);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* M68KRead8(a):
|
|
|
|
* M68KRead16(a):
|
|
|
|
* M68KRead32(a):
|
|
|
|
*
|
|
|
|
* Read data from the data address space.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* a Address to read from.
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* The 8, 16, or 32-bit value read.
|
|
|
|
*/
|
|
|
|
unsigned int FASTCALL M68KRead8(unsigned int a);
|
|
|
|
unsigned int FASTCALL M68KRead16(unsigned int a);
|
|
|
|
unsigned int FASTCALL M68KRead32(unsigned int a);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* M68KWrite8(a, d):
|
|
|
|
* M68KWrite16(a, d):
|
|
|
|
* M68KWrite32(a, d):
|
|
|
|
*
|
|
|
|
* Writes to the data address space.
|
|
|
|
*
|
|
|
|
* Parameters:
|
|
|
|
* a Address to write to.
|
|
|
|
* d Data to write.
|
|
|
|
*/
|
|
|
|
void FASTCALL M68KWrite8(unsigned int a, unsigned int d);
|
|
|
|
void FASTCALL M68KWrite16(unsigned int a, unsigned int d);
|
|
|
|
void FASTCALL M68KWrite32(unsigned int a, unsigned int d);
|
|
|
|
|
2011-07-31 02:37:31 +00:00
|
|
|
} // extern "C"
|
2011-07-12 04:57:12 +00:00
|
|
|
|
|
|
|
|
2011-07-31 02:37:31 +00:00
|
|
|
#endif // INCLUDED_68K_H
|