www.pudn.com > ncdzsrc.rar > asmintf.c
/***************************************************************************
asmintf.c
Handling A68K MC68000 core.
***************************************************************************/
#include "neogeocd.h"
typedef struct
{
UINT32 d[8]; /* 0x0004 8 Data registers */
UINT32 a[8]; /* 0x0024 8 Address registers */
UINT32 isp; /* 0x0048 */
UINT32 sr_high; /* 0x004C System registers */
UINT32 ccr; /* 0x0050 CCR in Intel Format */
UINT32 x_carry; /* 0x0054 Extended Carry */
UINT32 pc; /* 0x0058 Program Counter */
UINT32 IRQ_level; /* 0x005C IRQ level you want the MC68K process (0=None) */
/* Backward compatible with C emulator - Only set in Debug compile */
UINT16 sr;
UINT16 filler;
int (*irq_callback)(int irqline);
UINT32 previous_pc; /* last PC used */
int (*reset_callback)(void);
UINT32 sfc; /* Source Function Code. (68010) */
UINT32 dfc; /* Destination Function Code. (68010) */
UINT32 usp; /* User Stack (All) */
UINT32 vbr; /* Vector Base Register. (68010) */
UINT32 BankID; /* Memory bank in use */
UINT32 CPUtype; /* CPU Type 0=68000,1=68010,2=68020 */
UINT32 FullPC;
struct m68k_memory_interface Memory_Interface;
} a68k_cpu_context;
extern void M68000_RESET(void);
extern int M68000_RUN(void);
extern a68k_cpu_context M68000_regs;
int m68k_ICount;
int illegal_op = 0;
int illegal_pc = 0;
int mem_amask = 0x00ffffff;
#if M68K_DEBUG
int m68k_debug = 0;
int m68k_trace = 0;
static char m68k_tracebuf[256];
#endif
static a68k_cpu_context cpu_context;
/* interface for 24-bit address bus, 16-bit data bus */
const struct m68k_memory_interface a68k_memory_intf =
{
0,
m68000_read_memory_8,
m68000_read_memory_16,
m68000_read_memory_32,
m68000_write_memory_8,
m68000_write_memory_16,
m68000_write_memory_32,
m68000_setopbase,
m68000_read_memory_8, /* Encrypted Versions - not use */
m68000_read_memory_16,
m68000_read_memory_32,
m68000_read_memory_16,
m68000_read_memory_32
};
void m68000_init(void)
{
memset((void *)&M68000_regs, 0, sizeof(M68000_regs));
M68000_RESET();
}
void m68000_reset(int param)
{
UINT32 m68k_opbase = param ? 0x000000 : 0xc00000;
memset((void *)&M68000_regs, 0, sizeof(M68000_regs));
M68000_regs.Memory_Interface = a68k_memory_intf;
m68000_setopbase(m68k_opbase);
m68000_set_reg(M68K_A7, m68000_read_memory_32(m68k_opbase));
m68000_set_reg(M68K_ISP, m68000_read_memory_32(m68k_opbase));
m68000_set_reg(M68K_USP, m68000_read_memory_32(m68k_opbase));
m68000_set_reg(M68K_PC, m68000_read_memory_32(m68k_opbase + 4));
m68000_set_reg(M68K_SR, 0x2700);
M68000_regs.sr_high = 0x27;
}
void m68000_exit(void)
{
/* nothing to do ? */
}
int m68000_execute(int cycles)
{
if (M68000_regs.IRQ_level == 0x80) return cycles; /* STOP with no IRQs */
m68k_ICount += cycles;
#if M68K_DEBUG
if (osd_is_key_pressed_memory(KEYCODE_F5))
{
m68k_debug = 1;
logerror("---- MC68000 trace start ----\n");
}
if (m68k_debug)
{
int start_cycles = cycles;
do
{
// int break_point = 0xffffff;
int StartCycle = m68k_ICount;
m68k_ICount = 0;
// ブレークポイント指定時はトレース開始
// if (M68000_regs.pc == break_point)
// m68k_trace = 1;
if (m68k_trace)
{
int opcode_len, pc, pause = 1;
pc = M68000_regs.pc;
opcode_len = m68000_dasm(m68k_tracebuf, pc);
M68000_RUN();
// 特定の範囲をスキップしたい場合は↓を変更
// if (M68000_regs.pc >= 0x000000 && M68000_regs.pc <= 0x000000)
// pause = 0;
if (pause)
{
logerror("%06x: %s\n", pc, m68k_tracebuf);
while (1)
{
if (osd_is_key_pressed_memory(KEYCODE_SPACE))
break;
if (osd_is_key_pressed_memory(KEYCODE_F4))
{
logerror("---- MC68000 trace end ----\n");
m68k_trace = 0;
break;
}
if (osd_is_key_pressed_memory(KEYCODE_F5))
{
logerror("---- MC68000 debug end ----\n");
m68k_debug = 0;
m68k_trace = 0;
break;
}
update_input_port();
}
}
}
else
{
M68000_RUN();
if (osd_is_key_pressed_memory(KEYCODE_F5))
{
logerror("---- MC68000 debug end ----\n");
m68k_trace = 0;
m68k_debug = 0;
}
if (osd_is_key_pressed_memory(KEYCODE_F4))
{
logerror("---- MC68000 trace start ----\n");
m68k_trace = 1;
}
}
if (M68000_regs.IRQ_level & 0x80)
{
logerror("---- cause NMI interrupt ----\n");
return (cycles - m68k_ICount);
}
m68k_ICount += StartCycle;
update_input_port();
} while (m68k_ICount > 0);
if ((M68000_regs.IRQ_level & 0x80) == 0)
{
logerror("cycles end\n");
}
}
else
#endif
M68000_RUN();
return (cycles - m68k_ICount);
}
unsigned m68000_get_reg(int regnum)
{
switch (regnum)
{
case REG_PC:
case M68K_PC: return M68000_regs.pc;
case REG_SP:
case M68K_ISP: return M68000_regs.isp;
case M68K_USP: return M68000_regs.usp;
case M68K_SR: return M68000_regs.sr;
case M68K_VBR: return M68000_regs.vbr;
case M68K_SFC: return M68000_regs.sfc;
case M68K_DFC: return M68000_regs.dfc;
case M68K_D0: return M68000_regs.d[0];
case M68K_D1: return M68000_regs.d[1];
case M68K_D2: return M68000_regs.d[2];
case M68K_D3: return M68000_regs.d[3];
case M68K_D4: return M68000_regs.d[4];
case M68K_D5: return M68000_regs.d[5];
case M68K_D6: return M68000_regs.d[6];
case M68K_D7: return M68000_regs.d[7];
case M68K_A0: return M68000_regs.a[0];
case M68K_A1: return M68000_regs.a[1];
case M68K_A2: return M68000_regs.a[2];
case M68K_A3: return M68000_regs.a[3];
case M68K_A4: return M68000_regs.a[4];
case M68K_A5: return M68000_regs.a[5];
case M68K_A6: return M68000_regs.a[6];
case M68K_A7: return M68000_regs.a[7];
case REG_PREVIOUSPC: return M68000_regs.previous_pc;
/* TODO: Verify that this is the right thing to do for the purpose? */
default:
if (regnum <= REG_SP_CONTENTS)
{
unsigned offset = M68000_regs.isp + 4 * (REG_SP_CONTENTS - regnum);
if (offset < 0xfffffd)
return (*a68k_memory_intf.read32)(offset);
}
}
return 0;
}
void m68000_set_reg(int regnum, unsigned val)
{
switch (regnum)
{
case REG_PC:
case M68K_PC:
M68000_regs.pc = val;
m68000_setopbase(val & 0xf00000);
break;
case REG_SP:
case M68K_ISP: M68000_regs.isp = val; break;
case M68K_USP: M68000_regs.usp = val; break;
case M68K_SR: M68000_regs.sr = val; break;
case M68K_VBR: M68000_regs.vbr = val; break;
case M68K_SFC: M68000_regs.sfc = val; break;
case M68K_DFC: M68000_regs.dfc = val; break;
case M68K_D0: M68000_regs.d[0] = val; break;
case M68K_D1: M68000_regs.d[1] = val; break;
case M68K_D2: M68000_regs.d[2] = val; break;
case M68K_D3: M68000_regs.d[3] = val; break;
case M68K_D4: M68000_regs.d[4] = val; break;
case M68K_D5: M68000_regs.d[5] = val; break;
case M68K_D6: M68000_regs.d[6] = val; break;
case M68K_D7: M68000_regs.d[7] = val; break;
case M68K_A0: M68000_regs.a[0] = val; break;
case M68K_A1: M68000_regs.a[1] = val; break;
case M68K_A2: M68000_regs.a[2] = val; break;
case M68K_A3: M68000_regs.a[3] = val; break;
case M68K_A4: M68000_regs.a[4] = val; break;
case M68K_A5: M68000_regs.a[5] = val; break;
case M68K_A6: M68000_regs.a[6] = val; break;
case M68K_A7: M68000_regs.a[7] = val; break;
/* TODO: Verify that this is the right thing to do for the purpose? */
default:
if (regnum <= REG_SP_CONTENTS)
{
unsigned offset = M68000_regs.isp + 4 * (REG_SP_CONTENTS - regnum);
if (offset < 0xfffffd)
(*a68k_memory_intf.write32)(offset, val);
}
}
}
INLINE void m68k_assert_irq(int int_line)
{
/* Save icount */
int StartCount = m68k_ICount;
M68000_regs.IRQ_level = int_line;
/* Now check for Interrupt */
m68k_ICount = -1;
M68000_RUN();
/* Restore Count */
m68k_ICount = StartCount;
}
INLINE void m68k_clear_irq(int int_line)
{
M68000_regs.IRQ_level = 0;
}
void m68000_set_irq_line(int irqline, int state)
{
if (irqline == IRQ_LINE_NMI)
irqline = 7;
switch (state)
{
case CLEAR_LINE:
m68k_clear_irq(irqline);
return;
case ASSERT_LINE:
m68k_assert_irq(irqline);
return;
default:
m68k_assert_irq(irqline);
return;
}
}
void m68000_set_irq_callback(int (*callback)(int irqline))
{
M68000_regs.irq_callback = callback;
}
void m68000_save_context(void)
{
memcpy(&cpu_context, &M68000_regs, sizeof(a68k_cpu_context));
}
void m68000_restore_context(void)
{
memcpy(&M68000_regs, &cpu_context, sizeof(a68k_cpu_context));
}
#if (M68K_DEBUG == 1)
#include "d68k.h"
unsigned m68000_dasm(char *buffer, unsigned pc)
{
return m68k_disassemble(buffer, pc);
}
#endif