#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "mfp_io.h"
#include "mfpemul.h"
#ifdef DEBUG
# include <sc68/msg68.h>
static const char * const regnames[] = {
"GPIP",
"AER",
"DDR",
"IERA",
"IERB",
"IPRA",
"IPRB",
"ISRA",
"ISRB",
"IMRA",
"IMRB",
"VR",
"TACR",
"TBCR",
"TCDCR",
"TADR",
"TBDR",
"TCDR",
"TDDR",
"SCR",
"UCR",
"RSR",
"TSR",
"UDR",
};
static const char * regname(int reg)
{
if (! (reg & 1) )
return "!ODD";
reg >>= 1;
if (reg < 0 || reg >= sizeof(regnames)/sizeof(*regnames))
return "!OOR";
return regnames[reg];
}
extern int mfp_cat;
# define REPORTR(N) TRACE68(mfp_cat, "mfp: R [%02x] -> $%02x (%s)\n", N, mfp->map[N], regname(N))
# define REPORTW(N,V) TRACE68(mfp_cat, "mfp: W [%02x] <- $%02x (%s)\n", N, V, regname(N))
#else
# define REPORTR(N)
# define REPORTW(N,V)
#endif
typedef struct {
io68_t io;
mfp_t mfp;
} mfp_io68_t;
#define cpu2bogo(mfpio,cycle) ((bogoc68_t)((cycle)*192u))
#define bogo2cpu(mfpio,bogoc) ((cycle68_t)((bogoc))/192u)
static int68_t mfpr_01(mfp_t * const mfp, const bogoc68_t bogoc) {
REPORTR(GPIP);
return mfp->map[GPIP];
}
static void mfpw_01(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
REPORTW(GPIP,v);
mfp->map[GPIP] = v;
}
static int68_t mfpr_03(mfp_t * const mfp, const bogoc68_t bogoc) {
REPORTR(AER);
return mfp->map[AER];
}
static void mfpw_03(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
REPORTW(AER,v);
mfp->map[AER]=v;
}
static int68_t mfpr_05(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[DDR];
}
static void mfpw_05(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
mfp->map[DDR] = v;
}
static int68_t mfpr_07(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[IERA];
}
static void mfpw_07(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
mfp->map[IPRA] &= v;
mfp->map[IERA] = v;
}
static int68_t mfpr_09(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[IERB];
}
static void mfpw_09(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
mfp->map[IPRB] &= v;
mfp->map[IERB] = v;
}
static int68_t mfpr_0B(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[IPRA];
}
static void mfpw_0B(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
mfp->map[IPRA] &= v;
}
static int68_t mfpr_0D(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[IPRB];
}
static void mfpw_0D(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
mfp->map[IPRB] &=v;
}
static int68_t mfpr_0F(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[ISRA];
}
static void mfpw_0F(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
mfp->map[ISRA] = v;
}
static int68_t mfpr_11(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[ISRB];
}
static void mfpw_11(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
mfp->map[ISRB] = v;
}
static int68_t mfpr_13(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[IMRA];
}
static void mfpw_13(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
mfp->map[IMRA] = v;
}
static int68_t mfpr_15(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[IMRB];
}
static void mfpw_15(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
mfp->map[IMRB] = v;
}
static int68_t mfpr_17(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[VR];
}
static void mfpw_17(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
mfp->map[VR] = v;
}
static int68_t mfpr_19(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[TACR];
}
static int68_t mfpr_1B(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[TBCR];
}
static int68_t mfpr_1D(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[TCDCR];
}
static int68_t mfpr_1F(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp_get_tdr(mfp, TIMER_A, bogoc);
}
static int68_t mfpr_21(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp_get_tdr(mfp, TIMER_B, bogoc);
}
static int68_t mfpr_23(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp_get_tdr(mfp, TIMER_C, bogoc);
}
static int68_t mfpr_25(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp_get_tdr(mfp, TIMER_D, bogoc);
}
static int68_t mfpr_27(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[SCR];
}
static void mfpw_27(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc) {
mfp->map[SCR] = v;
}
static int68_t mfpr_29(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x29];
}
static int68_t mfpr_2B(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x2B];
}
static int68_t mfpr_2D(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x2D];
}
static int68_t mfpr_2F(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x2F];
}
static int68_t mfpr_31(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x31];
}
static int68_t mfpr_33(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x33];
}
static int68_t mfpr_35(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x35];
}
static int68_t mfpr_37(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x37];
}
static int68_t mfpr_39(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x39];
}
static int68_t mfpr_3B(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x3B];
}
static int68_t mfpr_3D(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x3D];
}
static int68_t mfpr_3F(mfp_t * const mfp, const bogoc68_t bogoc) {
return mfp->map[0x3F];
}
static void mfpw_19(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp_put_tcr(mfp, TIMER_A, v, bogoc); }
static void mfpw_1B(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp_put_tcr(mfp, TIMER_B, v, bogoc); }
static void mfpw_1D(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp_put_tcr(mfp, TIMER_C, v, bogoc); }
static void mfpw_1F(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp_put_tdr(mfp, TIMER_A, v, bogoc); }
static void mfpw_21(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp_put_tdr(mfp, TIMER_B, v, bogoc); }
static void mfpw_23(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp_put_tdr(mfp, TIMER_C, v, bogoc); }
static void mfpw_25(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp_put_tdr(mfp, TIMER_D, v, bogoc); }
static void mfpw_29(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x29]=v; }
static void mfpw_2B(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x2B]=v; }
static void mfpw_2D(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x2D]=v; }
static void mfpw_2F(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x2F]=v; }
static void mfpw_31(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x31]=v; }
static void mfpw_33(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x33]=v; }
static void mfpw_35(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x35]=v; }
static void mfpw_37(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x37]=v; }
static void mfpw_39(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x39]=v; }
static void mfpw_3B(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x3B]=v; }
static void mfpw_3D(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x3D]=v; }
static void mfpw_3F(mfp_t * const mfp, const int68_t v, const bogoc68_t bogoc)
{ mfp->map[0x3F]=v; }
static int68_t (* const mfpr_func[32])
(mfp_t * const, const bogoc68_t) =
{
mfpr_01,mfpr_03,mfpr_05,mfpr_07,
mfpr_09,mfpr_0B,mfpr_0D,mfpr_0F,
mfpr_11,mfpr_13,mfpr_15,mfpr_17,
mfpr_19,mfpr_1B,mfpr_1D,mfpr_1F,
mfpr_21,mfpr_23,mfpr_25,mfpr_27,
mfpr_29,mfpr_2B,mfpr_2D,mfpr_2F,
mfpr_31,mfpr_33,mfpr_35,mfpr_37,
mfpr_39,mfpr_3B,mfpr_3D,mfpr_3F,
};
static void (* const mfpw_func[32])
(mfp_t * const, const int68_t, const bogoc68_t) =
{
mfpw_01,mfpw_03,mfpw_05,mfpw_07,
mfpw_09,mfpw_0B,mfpw_0D,mfpw_0F,
mfpw_11,mfpw_13,mfpw_15,mfpw_17,
mfpw_19,mfpw_1B,mfpw_1D,mfpw_1F,
mfpw_21,mfpw_23,mfpw_25,mfpw_27,
mfpw_29,mfpw_2B,mfpw_2D,mfpw_2F,
mfpw_31,mfpw_33,mfpw_35,mfpw_37,
mfpw_39,mfpw_3B,mfpw_3D,mfpw_3F,
};
static int68_t _mfp_readB(mfp_io68_t * const mfpio, const int addr,
const bogoc68_t bogoc)
{
return !(addr&1)
? 0
: mfpr_func[(addr>>1)&0x1f](&mfpio->mfp, bogoc)
;
}
static void mfpio_readB(io68_t * const io)
{
const bogoc68_t bogoc = cpu2bogo(io,io->emu68->cycle);
io->emu68->bus_data =
_mfp_readB((mfp_io68_t *)io,
io->emu68->bus_addr, bogoc);
}
static void mfpio_readW(io68_t * const io)
{
const bogoc68_t bogoc = cpu2bogo(io,io->emu68->cycle);
io->emu68->bus_data =
_mfp_readB((mfp_io68_t *)io,
io->emu68->bus_addr+1, bogoc);
}
static void mfpio_readL(io68_t * const io)
{
const bogoc68_t bogoc = cpu2bogo(io,io->emu68->cycle);
const int addr = io->emu68->bus_addr;
io->emu68->bus_data =
(_mfp_readB((mfp_io68_t *)io, addr+1, bogoc)<<16)
|_mfp_readB((mfp_io68_t *)io, addr+3, bogoc);
}
static inline void _mfp_writeB(mfp_io68_t * const mfpio, const int addr,
const int68_t v, const bogoc68_t bogoc)
{
if (!(addr&1)) return;
mfpw_func[(addr>>1)&0x1f](&mfpio->mfp, (u8)v, bogoc);
}
static void mfpio_writeB(io68_t * const io)
{
mfp_io68_t * const mfpio = (mfp_io68_t * const)io;
const bogoc68_t bogoc = cpu2bogo(io,io->emu68->cycle);
_mfp_writeB(mfpio, io->emu68->bus_addr, io->emu68->bus_data, bogoc);
}
static void mfpio_writeW(io68_t * const io)
{
mfp_io68_t * const mfpio = (mfp_io68_t * const)io;
const bogoc68_t bogoc = cpu2bogo(io,io->emu68->cycle);
_mfp_writeB(mfpio, io->emu68->bus_addr+1, io->emu68->bus_data, bogoc);
}
static void mfpio_writeL(io68_t * const io)
{
mfp_io68_t * const mfpio = (mfp_io68_t * const)io;
const bogoc68_t bogoc = cpu2bogo(io,io->emu68->cycle);
_mfp_writeB(mfpio,
io->emu68->bus_addr+1, io->emu68->bus_data>>16, bogoc);
_mfp_writeB((mfp_io68_t *)io,
io->emu68->bus_addr+3, io->emu68->bus_data ,bogoc);
}
static int mfpio_reset(io68_t * const io)
{
mfp_io68_t * const mfpio = (mfp_io68_t * const)io;
const bogoc68_t bogoc = cpu2bogo(io,io->emu68->cycle);
mfp_reset(&mfpio->mfp,bogoc);
return 0;
}
static interrupt68_t * mfpio_interrupt(io68_t * const io,
const cycle68_t cycle)
{
mfp_io68_t * const mfpio = (mfp_io68_t * const)io;
const bogoc68_t bogoc = cpu2bogo(io,cycle);
interrupt68_t * const inter =
mfp_interrupt(&mfpio->mfp, bogoc);
if (inter) {
#ifdef DEBUG
if (inter->cycle >= bogoc) {
*(int *)0 = 0xDEADBEEF;
}
#endif
inter->cycle = bogo2cpu(io,inter->cycle);
#ifdef DEBUG
if (inter->cycle >= cycle) {
*(int *)0 = 0xDEADBEEF;
}
#endif
}
return inter;
}
static void mfpio_adjust_cycle(io68_t * const io,
const cycle68_t cycle)
{
mfp_io68_t * const mfpio = (mfp_io68_t * const)io;
const bogoc68_t bogoc = cpu2bogo(io, cycle);
mfp_adjust_bogoc(&mfpio->mfp, bogoc);
}
void mfpio_destroy(io68_t * const io)
{
mfp_io68_t * const mfpio = (mfp_io68_t * const)io;
if (io) {
mfp_cleanup(&mfpio->mfp);
emu68_free(io);
}
}
static io68_t mfp_io =
{
0,
"MK-68901",
0xFFFFFA00, 0xFFFFFA2F,
mfpio_readB,mfpio_readW,mfpio_readL,
mfpio_writeB,mfpio_writeW,mfpio_writeL,
mfpio_interrupt,0,
mfpio_adjust_cycle,
mfpio_reset,
mfpio_destroy
};
int mfpio_init(int * argc, char ** argv)
{
return mfp_init();
}
void mfpio_shutdown(void)
{
mfp_shutdown();
}
io68_t * mfpio_create(emu68_t * const emu68)
{
mfp_io68_t * mfpio = 0;
if (emu68) {
mfpio = emu68_alloc(sizeof(*mfpio));
if (mfpio) {
mfpio->io = mfp_io;
mfp_setup(&mfpio->mfp);
}
}
return &mfpio->io;
}