Files
2026-10-27 18:56:54 +01:00

957 lines
35 KiB
C

/******************************************************************************
m68000.c
M68000 CPU¥¤¥ó¥¿¥Õ¥§¡¼¥¹´Ø¿ô
******************************************************************************/
#include "m68000.h"
#if defined (HAVE_CYCLONE)
struct Cyclone m68k;
#endif
#if defined (HAVE_C68K)
#include "c68k/c68k.h"
#endif
#if defined (HAVE_M68000)
#include "m68k/c68k.h"
#endif
#if defined (HAVE_MUSASHI)
#include "musashi/m68k.h"
#include "musashi/m68kcpu.h"
#endif
#ifdef HAVE_CPU_RUNTIME
static int m68000_use_musashi = 0;
void m68000_set_emulation(int use_musashi) { m68000_use_musashi = use_musashi ? 1 : 0; }
int m68000_get_emulation(void) { return m68000_use_musashi; }
#else
void m68000_set_emulation(int use_musashi) { (void)use_musashi; }
int m68000_get_emulation(void) { return 0; }
#endif
#include "../x68k/x68kmemory.h"
int m68000_ICountBk;
int ICount;
#ifdef HAVE_CPU_RUNTIME
/* Runtime-selectable CPU state format.
*
* The common register set makes save states portable between C68K and
* Musashi. Backend-specific transient state is also stored so same-backend
* restores (including RetroArch Run-Ahead) retain the existing precision.
*/
static int m68000_RuntimeStateAction(StateMem *sm, int load, int data_only)
{
uint32_t format_version = 0;
uint32_t backend = 0;
uint32_t reg_d[8] = {0}, reg_a[8] = {0};
uint32_t reg_pc = 0, reg_sr = 0, reg_usp = 0, reg_ssp = 0;
uint32_t reg_irq_level = 0, reg_stopped = 0;
uint32_t raw_c68k_d[8] = {0}, raw_c68k_a[8] = {0};
uint32_t raw_c68k_flag_c = 0, raw_c68k_flag_v = 0;
uint32_t raw_c68k_flag_notz = 0, raw_c68k_flag_n = 0;
uint32_t raw_c68k_flag_x = 0, raw_c68k_flag_i = 0, raw_c68k_flag_s = 0;
uint32_t raw_c68k_usp = 0, raw_c68k_pc = 0, raw_c68k_halt = 0;
int32_t raw_c68k_irq_line = 0, raw_c68k_irq_state = 0;
int32_t raw_c68k_icount = 0, raw_c68k_icount_bk = 0;
uint32_t raw_m_c_flag = 0, raw_m_v_flag = 0, raw_m_not_z_flag = 0;
uint32_t raw_m_n_flag = 0, raw_m_x_flag = 0, raw_m_m_flag = 0;
uint32_t raw_m_s_flag = 0, raw_m_int_level = 0, raw_m_stopped = 0;
int32_t raw_m_remaining_cycles = 0;
int ret;
SFORMAT StateRegs[] = {
SFVARN(format_version, "CPU_STATE_FORMAT"),
SFVARN(backend, "CPU_STATE_BACKEND"),
SFVARN(reg_d[0], "REG_D0"), SFVARN(reg_d[1], "REG_D1"),
SFVARN(reg_d[2], "REG_D2"), SFVARN(reg_d[3], "REG_D3"),
SFVARN(reg_d[4], "REG_D4"), SFVARN(reg_d[5], "REG_D5"),
SFVARN(reg_d[6], "REG_D6"), SFVARN(reg_d[7], "REG_D7"),
SFVARN(reg_a[0], "REG_A0"), SFVARN(reg_a[1], "REG_A1"),
SFVARN(reg_a[2], "REG_A2"), SFVARN(reg_a[3], "REG_A3"),
SFVARN(reg_a[4], "REG_A4"), SFVARN(reg_a[5], "REG_A5"),
SFVARN(reg_a[6], "REG_A6"), SFVARN(reg_a[7], "REG_A7"),
SFVARN(reg_pc, "REG_PC"), SFVARN(reg_sr, "REG_SR"),
SFVARN(reg_usp, "REG_USP"), SFVARN(reg_ssp, "REG_SSP"),
SFVARN(reg_irq_level, "REG_IRQ_LEVEL"),
SFVARN(reg_stopped, "REG_STOPPED"),
/* Keep the legacy C68K names for named-state backward compatibility. */
SFVARN(raw_c68k_d[0], "D0"), SFVARN(raw_c68k_d[1], "D1"),
SFVARN(raw_c68k_d[2], "D2"), SFVARN(raw_c68k_d[3], "D3"),
SFVARN(raw_c68k_d[4], "D4"), SFVARN(raw_c68k_d[5], "D5"),
SFVARN(raw_c68k_d[6], "D6"), SFVARN(raw_c68k_d[7], "D7"),
SFVARN(raw_c68k_a[0], "A0"), SFVARN(raw_c68k_a[1], "A1"),
SFVARN(raw_c68k_a[2], "A2"), SFVARN(raw_c68k_a[3], "A3"),
SFVARN(raw_c68k_a[4], "A4"), SFVARN(raw_c68k_a[5], "A5"),
SFVARN(raw_c68k_a[6], "A6"), SFVARN(raw_c68k_a[7], "A7"),
SFVARN(raw_c68k_flag_c, "flag_C"), SFVARN(raw_c68k_flag_v, "flag_V"),
SFVARN(raw_c68k_flag_notz, "flag_notZ"), SFVARN(raw_c68k_flag_n, "flag_N"),
SFVARN(raw_c68k_flag_x, "flag_X"), SFVARN(raw_c68k_flag_i, "flag_I"),
SFVARN(raw_c68k_flag_s, "flag_S"), SFVARN(raw_c68k_usp, "USP"),
SFVARN(raw_c68k_pc, "PC"), SFVARN(raw_c68k_halt, "HaltState"),
SFVARN(raw_c68k_irq_line, "IRQLine"), SFVARN(raw_c68k_irq_state, "IRQState"),
SFVARN(raw_c68k_icount, "ICount"), SFVARN(raw_c68k_icount_bk, "ICountBk"),
/* Musashi transient state: present in every state for a fixed layout. */
SFVARN(raw_m_c_flag, "MUSASHI_c_flag"),
SFVARN(raw_m_v_flag, "MUSASHI_v_flag"),
SFVARN(raw_m_not_z_flag, "MUSASHI_not_z_flag"),
SFVARN(raw_m_n_flag, "MUSASHI_n_flag"),
SFVARN(raw_m_x_flag, "MUSASHI_x_flag"),
SFVARN(raw_m_m_flag, "MUSASHI_m_flag"),
SFVARN(raw_m_s_flag, "MUSASHI_s_flag"),
SFVARN(raw_m_int_level, "MUSASHI_int_level"),
SFVARN(raw_m_stopped, "MUSASHI_stopped"),
SFVARN(raw_m_remaining_cycles, "MUSASHI_remaining_cycles"),
SFEND
};
if (!load)
{
int i;
format_version = 1;
backend = m68000_use_musashi ? 1u : 0u;
for (i = 0; i < 8; i++)
{
if (backend)
{
reg_d[i] = m68k_get_reg(NULL, (m68k_register_t)(M68K_REG_D0 + i));
reg_a[i] = m68k_get_reg(NULL, (m68k_register_t)(M68K_REG_A0 + i));
}
else
{
reg_d[i] = C68k_Get_Reg(&C68K, C68K_D0 + i);
reg_a[i] = C68k_Get_Reg(&C68K, C68K_A0 + i);
raw_c68k_d[i] = C68K.D[i];
raw_c68k_a[i] = C68K.A[i];
}
}
if (backend)
{
reg_pc = m68k_get_reg(NULL, M68K_REG_PC);
reg_sr = m68k_get_reg(NULL, M68K_REG_SR);
reg_usp = m68k_get_reg(NULL, M68K_REG_USP);
reg_ssp = m68k_get_reg(NULL, M68K_REG_ISP);
reg_irq_level = m68ki_cpu.int_level;
reg_stopped = m68ki_cpu.stopped != 0;
raw_m_c_flag = m68ki_cpu.c_flag;
raw_m_v_flag = m68ki_cpu.v_flag;
raw_m_not_z_flag = m68ki_cpu.not_z_flag;
raw_m_n_flag = m68ki_cpu.n_flag;
raw_m_x_flag = m68ki_cpu.x_flag;
raw_m_m_flag = m68ki_cpu.m_flag;
raw_m_s_flag = m68ki_cpu.s_flag;
raw_m_int_level = m68ki_cpu.int_level;
raw_m_stopped = m68ki_cpu.stopped;
raw_m_remaining_cycles = m68ki_remaining_cycles;
}
else
{
reg_pc = C68k_Get_Reg(&C68K, C68K_PC);
reg_sr = C68k_Get_Reg(&C68K, C68K_SR);
reg_usp = C68k_Get_Reg(&C68K, C68K_USP);
reg_ssp = C68k_Get_Reg(&C68K, C68K_MSP);
reg_irq_level = (C68K.IRQState == CLEAR_LINE) ? 0u : (uint32_t)C68K.IRQLine;
reg_stopped = C68K.HaltState != 0;
raw_c68k_flag_c = C68K.flag_C; raw_c68k_flag_v = C68K.flag_V;
raw_c68k_flag_notz = C68K.flag_notZ; raw_c68k_flag_n = C68K.flag_N;
raw_c68k_flag_x = C68K.flag_X; raw_c68k_flag_i = C68K.flag_I;
raw_c68k_flag_s = C68K.flag_S; raw_c68k_usp = C68K.USP;
raw_c68k_pc = reg_pc; raw_c68k_halt = C68K.HaltState;
raw_c68k_irq_line = C68K.IRQLine; raw_c68k_irq_state = C68K.IRQState;
raw_c68k_icount = C68K.ICount; raw_c68k_icount_bk = C68K.ICountBk;
}
return PX68KSS_StateAction(sm, 0, data_only, StateRegs, "X68K_CPU", false);
}
ret = PX68KSS_StateAction(sm, 1, data_only, StateRegs, "X68K_CPU", false);
if (ret && format_version == 1)
{
int i;
if (backend == (uint32_t)(m68000_use_musashi ? 1 : 0))
{
if (m68000_use_musashi)
{
for (i = 0; i < 8; i++)
{
m68k_set_reg((m68k_register_t)(M68K_REG_D0 + i), reg_d[i]);
m68k_set_reg((m68k_register_t)(M68K_REG_A0 + i), reg_a[i]);
}
m68k_set_reg(M68K_REG_SR, reg_sr);
m68k_set_reg(M68K_REG_USP, reg_usp);
m68k_set_reg(M68K_REG_ISP, reg_ssp);
m68k_set_reg(M68K_REG_A7, reg_a[7]);
m68k_set_reg(M68K_REG_PC, reg_pc);
m68ki_cpu.c_flag = raw_m_c_flag; m68ki_cpu.v_flag = raw_m_v_flag;
m68ki_cpu.not_z_flag = raw_m_not_z_flag; m68ki_cpu.n_flag = raw_m_n_flag;
m68ki_cpu.x_flag = raw_m_x_flag; m68ki_cpu.m_flag = raw_m_m_flag;
m68ki_cpu.s_flag = raw_m_s_flag; m68ki_cpu.int_level = raw_m_int_level;
m68ki_cpu.stopped = raw_m_stopped;
m68ki_remaining_cycles = raw_m_remaining_cycles;
}
else
{
for (i = 0; i < 8; i++)
{
C68K.D[i] = raw_c68k_d[i]; C68K.A[i] = raw_c68k_a[i];
}
C68K.flag_C = raw_c68k_flag_c; C68K.flag_V = raw_c68k_flag_v;
C68K.flag_notZ = raw_c68k_flag_notz; C68K.flag_N = raw_c68k_flag_n;
C68K.flag_X = raw_c68k_flag_x; C68K.flag_I = raw_c68k_flag_i;
C68K.flag_S = raw_c68k_flag_s; C68K.USP = raw_c68k_usp;
C68k_Set_Reg(&C68K, C68K_PC, raw_c68k_pc);
C68K.HaltState = raw_c68k_halt; C68K.IRQLine = raw_c68k_irq_line;
C68K.IRQState = raw_c68k_irq_state; C68K.ICount = raw_c68k_icount;
C68K.ICountBk = raw_c68k_icount_bk;
}
}
else if (m68000_use_musashi)
{
/* Cross-load C68K state into Musashi using architectural state. */
for (i = 0; i < 8; i++)
{
m68k_set_reg((m68k_register_t)(M68K_REG_D0 + i), reg_d[i]);
m68k_set_reg((m68k_register_t)(M68K_REG_A0 + i), reg_a[i]);
}
m68k_set_reg(M68K_REG_SR, reg_sr); m68k_set_reg(M68K_REG_USP, reg_usp);
m68k_set_reg(M68K_REG_ISP, reg_ssp); m68k_set_reg(M68K_REG_A7, reg_a[7]);
m68k_set_reg(M68K_REG_PC, reg_pc);
m68ki_cpu.int_level = reg_irq_level;
m68ki_cpu.stopped = reg_stopped ? STOP_LEVEL_STOP : 0;
m68ki_remaining_cycles = 0;
}
else
{
/* Cross-load Musashi state into C68K using architectural state. */
for (i = 0; i < 8; i++)
{
C68k_Set_Reg(&C68K, C68K_D0 + i, reg_d[i]);
C68k_Set_Reg(&C68K, C68K_A0 + i, reg_a[i]);
}
C68k_Set_Reg(&C68K, C68K_SR, reg_sr);
C68k_Set_Reg(&C68K, C68K_USP, reg_usp);
C68k_Set_Reg(&C68K, C68K_MSP, reg_ssp);
C68k_Set_Reg(&C68K, C68K_A7, reg_a[7]);
C68k_Set_Reg(&C68K, C68K_PC, reg_pc);
C68K.IRQLine = (int32_t)reg_irq_level;
C68K.IRQState = reg_irq_level ? HOLD_LINE : CLEAR_LINE;
C68K.HaltState = reg_stopped ? 1u : 0u;
C68K.ICount = 0; C68K.ICountBk = 0;
}
return 1;
}
if (ret)
{
/* Older named C68K states lack the format marker; restore their fields. */
int i;
for (i = 0; i < 8; i++) { C68K.D[i] = raw_c68k_d[i]; C68K.A[i] = raw_c68k_a[i]; }
C68K.flag_C = raw_c68k_flag_c; C68K.flag_V = raw_c68k_flag_v;
C68K.flag_notZ = raw_c68k_flag_notz; C68K.flag_N = raw_c68k_flag_n;
C68K.flag_X = raw_c68k_flag_x; C68K.flag_I = raw_c68k_flag_i;
C68K.flag_S = raw_c68k_flag_s; C68K.USP = raw_c68k_usp;
C68k_Set_Reg(&C68K, C68K_PC, raw_c68k_pc); C68K.HaltState = raw_c68k_halt;
C68K.IRQLine = raw_c68k_irq_line; C68K.IRQState = raw_c68k_irq_state;
C68K.ICount = raw_c68k_icount; C68K.ICountBk = raw_c68k_icount_bk;
if (m68000_use_musashi)
{
/* Convert an older C68K-only save into the currently selected Musashi backend. */
for (i = 0; i < 8; i++)
{
m68k_set_reg((m68k_register_t)(M68K_REG_D0 + i), C68K.D[i]);
m68k_set_reg((m68k_register_t)(M68K_REG_A0 + i), C68K.A[i]);
}
m68k_set_reg(M68K_REG_SR, C68k_Get_Reg(&C68K, C68K_SR));
m68k_set_reg(M68K_REG_USP, C68k_Get_Reg(&C68K, C68K_USP));
m68k_set_reg(M68K_REG_ISP, C68k_Get_Reg(&C68K, C68K_MSP));
m68k_set_reg(M68K_REG_A7, C68K.A[7]);
m68k_set_reg(M68K_REG_PC, C68k_Get_Reg(&C68K, C68K_PC));
m68ki_cpu.int_level = (C68K.IRQState == CLEAR_LINE) ? 0u : (uint32_t)C68K.IRQLine;
m68ki_cpu.stopped = C68K.HaltState ? STOP_LEVEL_STOP : 0;
m68ki_remaining_cycles = 0;
}
return 1;
}
/* Backward compatibility for old Musashi-only save states. */
{
uint32_t tmp32[20] = {0};
uint32_t c_flag = 0, v_flag = 0, not_z_flag = 0, n_flag = 0;
uint32_t x_flag = 0, m_flag = 0, s_flag = 0, int_level = 0, stopped = 0;
int32_t remaining_cycles = 0;
SFORMAT LegacyMusashiRegs[] = {
SFVARN(tmp32[0], "M68K_REG_D0"), SFVARN(tmp32[1], "M68K_REG_D1"),
SFVARN(tmp32[2], "M68K_REG_D2"), SFVARN(tmp32[3], "M68K_REG_D3"),
SFVARN(tmp32[4], "M68K_REG_D4"), SFVARN(tmp32[5], "M68K_REG_D5"),
SFVARN(tmp32[6], "M68K_REG_D6"), SFVARN(tmp32[7], "M68K_REG_D7"),
SFVARN(tmp32[8], "M68K_REG_A0"), SFVARN(tmp32[9], "M68K_REG_A1"),
SFVARN(tmp32[10], "M68K_REG_A2"), SFVARN(tmp32[11], "M68K_REG_A3"),
SFVARN(tmp32[12], "M68K_REG_A4"), SFVARN(tmp32[13], "M68K_REG_A5"),
SFVARN(tmp32[14], "M68K_REG_A6"), SFVARN(tmp32[15], "M68K_REG_A7"),
SFVARN(tmp32[16], "M68K_REG_PC"), SFVARN(tmp32[17], "M68K_REG_SR"),
SFVARN(tmp32[18], "M68K_REG_USP"), SFVARN(tmp32[19], "M68K_REG_ISP"),
SFVARN(c_flag, "m68ki_cpu.c_flag"), SFVARN(v_flag, "m68ki_cpu.v_flag"),
SFVARN(not_z_flag, "m68ki_cpu.not_z_flag"), SFVARN(n_flag, "m68ki_cpu.n_flag"),
SFVARN(x_flag, "m68ki_cpu.x_flag"), SFVARN(m_flag, "m68ki_cpu.m_flag"),
SFVARN(s_flag, "m68ki_cpu.s_flag"), SFVARN(int_level, "m68ki_cpu.int_level"),
SFVARN(stopped, "m68ki_cpu.stopped"),
SFVARN(remaining_cycles, "m68ki_remaining_cycles"), SFEND
};
ret = PX68KSS_StateAction(sm, 1, data_only, LegacyMusashiRegs, "MUSASHI_CPU", false);
if (!ret) return 0;
for (int i = 0; i < 8; i++)
{
m68k_set_reg((m68k_register_t)(M68K_REG_D0 + i), tmp32[i]);
m68k_set_reg((m68k_register_t)(M68K_REG_A0 + i), tmp32[8 + i]);
}
m68k_set_reg(M68K_REG_SR, tmp32[17]); m68k_set_reg(M68K_REG_USP, tmp32[18]);
m68k_set_reg(M68K_REG_ISP, tmp32[19]); m68k_set_reg(M68K_REG_A7, tmp32[15]);
m68k_set_reg(M68K_REG_PC, tmp32[16]);
m68ki_cpu.c_flag = c_flag; m68ki_cpu.v_flag = v_flag; m68ki_cpu.not_z_flag = not_z_flag;
m68ki_cpu.n_flag = n_flag; m68ki_cpu.x_flag = x_flag; m68ki_cpu.m_flag = m_flag;
m68ki_cpu.s_flag = s_flag; m68ki_cpu.int_level = int_level; m68ki_cpu.stopped = stopped;
m68ki_remaining_cycles = remaining_cycles;
if (!m68000_use_musashi)
{
for (int i = 0; i < 8; i++)
{
C68k_Set_Reg(&C68K, C68K_D0 + i, tmp32[i]);
C68k_Set_Reg(&C68K, C68K_A0 + i, tmp32[8 + i]);
}
C68k_Set_Reg(&C68K, C68K_SR, tmp32[17]);
C68k_Set_Reg(&C68K, C68K_USP, tmp32[18]);
C68k_Set_Reg(&C68K, C68K_MSP, tmp32[19]);
C68k_Set_Reg(&C68K, C68K_A7, tmp32[15]); C68k_Set_Reg(&C68K, C68K_PC, tmp32[16]);
C68K.IRQLine = (int32_t)int_level; C68K.IRQState = int_level ? HOLD_LINE : CLEAR_LINE;
C68K.HaltState = stopped ? 1u : 0u; C68K.ICount = 0; C68K.ICountBk = 0;
}
return 1;
}
}
#endif
int m68000_StateAction(StateMem *sm, int load, int data_only)
{
#ifdef HAVE_CPU_RUNTIME
return m68000_RuntimeStateAction(sm, load, data_only);
#endif
#ifdef HAVE_C68K
int ret = 0;
uint32_t pc = 0;
SFORMAT StateRegs[] =
{
SFVARN(C68K.D[0], "D0"),
SFVARN(C68K.D[1], "D1"),
SFVARN(C68K.D[2], "D2"),
SFVARN(C68K.D[3], "D3"),
SFVARN(C68K.D[4], "D4"),
SFVARN(C68K.D[5], "D5"),
SFVARN(C68K.D[6], "D6"),
SFVARN(C68K.D[7], "D7"),
SFVARN(C68K.A[0], "A0"),
SFVARN(C68K.A[1], "A1"),
SFVARN(C68K.A[2], "A2"),
SFVARN(C68K.A[3], "A3"),
SFVARN(C68K.A[4], "A4"),
SFVARN(C68K.A[5], "A5"),
SFVARN(C68K.A[6], "A6"),
SFVARN(C68K.A[7], "A7"),
SFVARN(C68K.flag_C, "flag_C"),
SFVARN(C68K.flag_V, "flag_V"),
SFVARN(C68K.flag_notZ, "flag_notZ"),
SFVARN(C68K.flag_X, "flag_X"),
SFVARN(C68K.flag_I, "flag_I"),
SFVARN(C68K.flag_S, "flag_S"),
SFVARN(C68K.USP, "USP"),
SFVARN(pc, "PC"),
SFVARN(C68K.Status, "status"),
SFVARN(C68K.IRQLine, "IRQLine"),
SFVARN(C68K.CycleToDo, "CycleToDo"),
SFVARN(C68K.CycleIO, "CycleIO"),
SFVARN(C68K.CycleSup, "CycleSup"),
SFVARN(C68K.dirty1, "dirtyflag"),
SFEND
};
if (!load)
pc = m68000_get_reg(M68K_PC);
ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "X68K_CPU", false);
if (load)
m68000_set_reg(M68K_PC, pc);
return ret;
#endif
#ifdef HAVE_MUSASHI
int ret = 0;
uint32_t tmp32[20];
SFORMAT StateRegs[] =
{
SFVARN(tmp32[0], "M68K_REG_D0"),
SFVARN(tmp32[1], "M68K_REG_D1"),
SFVARN(tmp32[2], "M68K_REG_D2"),
SFVARN(tmp32[3], "M68K_REG_D3"),
SFVARN(tmp32[4], "M68K_REG_D4"),
SFVARN(tmp32[5], "M68K_REG_D5"),
SFVARN(tmp32[6], "M68K_REG_D6"),
SFVARN(tmp32[7], "M68K_REG_D7"),
SFVARN(tmp32[8], "M68K_REG_A0"),
SFVARN(tmp32[9], "M68K_REG_A1"),
SFVARN(tmp32[10], "M68K_REG_A2"),
SFVARN(tmp32[11], "M68K_REG_A3"),
SFVARN(tmp32[12], "M68K_REG_A4"),
SFVARN(tmp32[13], "M68K_REG_A5"),
SFVARN(tmp32[14], "M68K_REG_A6"),
SFVARN(tmp32[15], "M68K_REG_A7"),
SFVARN(tmp32[16], "M68K_REG_PC"),
SFVARN(tmp32[17], "M68K_REG_SR"),
SFVARN(tmp32[18], "M68K_REG_USP"),
SFVARN(tmp32[19], "M68K_REG_ISP"),
SFVAR(m68ki_cpu.c_flag),
SFVAR(m68ki_cpu.v_flag),
SFVAR(m68ki_cpu.not_z_flag),
SFVAR(m68ki_cpu.n_flag),
SFVAR(m68ki_cpu.x_flag),
SFVAR(m68ki_cpu.m_flag),
SFVAR(m68ki_cpu.s_flag),
SFVAR(m68ki_cpu.int_level),
SFVAR(m68ki_cpu.stopped),
SFVAR(m68ki_remaining_cycles),
SFEND
};
if (!load)
{
tmp32[0] = m68k_get_reg(NULL, M68K_REG_D0);
tmp32[1] = m68k_get_reg(NULL, M68K_REG_D1);
tmp32[2] = m68k_get_reg(NULL, M68K_REG_D2);
tmp32[3] = m68k_get_reg(NULL, M68K_REG_D3);
tmp32[4] = m68k_get_reg(NULL, M68K_REG_D4);
tmp32[5] = m68k_get_reg(NULL, M68K_REG_D5);
tmp32[6] = m68k_get_reg(NULL, M68K_REG_D6);
tmp32[7] = m68k_get_reg(NULL, M68K_REG_D7);
tmp32[8] = m68k_get_reg(NULL, M68K_REG_A0);
tmp32[9] = m68k_get_reg(NULL, M68K_REG_A1);
tmp32[10] = m68k_get_reg(NULL, M68K_REG_A2);
tmp32[11] = m68k_get_reg(NULL, M68K_REG_A3);
tmp32[12] = m68k_get_reg(NULL, M68K_REG_A4);
tmp32[13] = m68k_get_reg(NULL, M68K_REG_A5);
tmp32[14] = m68k_get_reg(NULL, M68K_REG_A6);
tmp32[15] = m68k_get_reg(NULL, M68K_REG_A7);
tmp32[16] = m68k_get_reg(NULL, M68K_REG_PC);
tmp32[17] = m68k_get_reg(NULL, M68K_REG_SR);
tmp32[18] = m68k_get_reg(NULL, M68K_REG_USP);
tmp32[19] = m68k_get_reg(NULL, M68K_REG_ISP);
}
ret = PX68KSS_StateAction(sm, load, data_only, StateRegs, "MUSASHI_CPU", false);
if (load)
{
m68k_set_reg(M68K_REG_D0, tmp32[0]);
m68k_set_reg(M68K_REG_D1, tmp32[1]);
m68k_set_reg(M68K_REG_D2, tmp32[2]);
m68k_set_reg(M68K_REG_D3, tmp32[3]);
m68k_set_reg(M68K_REG_D4, tmp32[4]);
m68k_set_reg(M68K_REG_D5, tmp32[5]);
m68k_set_reg(M68K_REG_D6, tmp32[6]);
m68k_set_reg(M68K_REG_D7, tmp32[7]);
m68k_set_reg(M68K_REG_A0, tmp32[8]);
m68k_set_reg(M68K_REG_A1, tmp32[9]);
m68k_set_reg(M68K_REG_A2, tmp32[10]);
m68k_set_reg(M68K_REG_A3, tmp32[11]);
m68k_set_reg(M68K_REG_A4, tmp32[12]);
m68k_set_reg(M68K_REG_A5, tmp32[13]);
m68k_set_reg(M68K_REG_A6, tmp32[14]);
m68k_set_reg(M68K_REG_A7, tmp32[15]);
m68k_set_reg(M68K_REG_PC, tmp32[16]);
m68k_set_reg(M68K_REG_SR, tmp32[17]);
m68k_set_reg(M68K_REG_USP, tmp32[18]);
m68k_set_reg(M68K_REG_ISP, tmp32[19]);
};
return ret;
#endif
}
#if defined (HAVE_CYCLONE)
unsigned int read8(unsigned int a) {
return (unsigned int) cpu_readmem24(a);
}
unsigned int read16(unsigned int a) {
return (unsigned int) cpu_readmem24_word(a);
}
unsigned int MyCheckPc(unsigned int pc)
{
pc-= m68k.membase; /* Get the real program counter */
if (pc <= 0xbfffff) { m68k.membase=(int) MEM; return m68k.membase+pc; }
if ((pc >= 0xfc0000) && (pc <= 0xffffff)) { m68k.membase=(int) IPL - 0xfc0000; return m68k.membase+pc; }
if ((pc >= 0xc00000) && (pc <= 0xc7ffff)) m68k.membase=(int) GVRAM - 0xc00000;
if ((pc >= 0xe00000) && (pc <= 0xe7ffff)) m68k.membase=(int) TVRAM - 0xe00000;
if ((pc >= 0xea0000) && (pc <= 0xea1fff)) m68k.membase=(int) SCSIIPL - 0xea0000;
if ((pc >= 0xed0000) && (pc <= 0xed3fff)) m68k.membase=(int) SRAM - 0xed0000;
if ((pc >= 0xf00000) && (pc <= 0xfbffff)) m68k.membase=(int) FONT - 0xf00000;
return m68k.membase+pc; /* New program counter */
}
#elif defined (HAVE_MUSASHI) || defined (HAVE_CPU_RUNTIME)
uint32_t m68k_read_memory_8(uint32_t address)
{
return (uint32_t) cpu_readmem24(address);
}
void m68k_write_memory_8(uint32_t address, uint32_t data)
{
cpu_writemem24(address, data);
}
uint32_t m68k_read_memory_16(uint32_t address)
{
return (uint32_t) cpu_readmem24_word(address);
}
void m68k_write_memory_16(uint32_t address, uint32_t data)
{
cpu_writemem24_word(address, data);
}
uint32_t m68k_read_memory_32(uint32_t address)
{
return (uint32_t) cpu_readmem24_dword(address);
}
void m68k_write_memory_32(uint32_t address, uint32_t data)
{
cpu_writemem24_dword(address, data);
}
#endif /* HAVE_CYCLONE */ /* HAVE_MUSASHI */
/******************************************************************************
M68000¥¤¥ó¥¿¥Õ¥§¡¼¥¹´Ø¿ô
******************************************************************************/
/*--------------------------------------------------------
CPU½é´ü²½
--------------------------------------------------------*/
#if !defined (HAVE_MUSASHI) || defined (HAVE_CPU_RUNTIME)
int32_t my_irqh_callback(int32_t level);
#endif
void m68000_init(void)
{
#ifdef HAVE_CPU_RUNTIME
C68k_Init(&C68K, my_irqh_callback);
C68k_Set_ReadB(&C68K, cpu_readmem24);
C68k_Set_ReadW(&C68K, cpu_readmem24_word);
C68k_Set_WriteB(&C68K, cpu_writemem24);
C68k_Set_WriteW(&C68K, cpu_writemem24_word);
C68k_Set_Fetch(&C68K, 0x000000, 0xbfffff, (uintptr_t)MEM);
C68k_Set_Fetch(&C68K, 0xc00000, 0xc7ffff, (uintptr_t)GVRAM);
C68k_Set_Fetch(&C68K, 0xe00000, 0xe7ffff, (uintptr_t)TVRAM);
C68k_Set_Fetch(&C68K, 0xea0000, 0xea1fff, (uintptr_t)SCSIIPL);
C68k_Set_Fetch(&C68K, 0xed0000, 0xed3fff, (uintptr_t)SRAM);
C68k_Set_Fetch(&C68K, 0xf00000, 0xfbffff, (uintptr_t)FONT);
C68k_Set_Fetch(&C68K, 0xfc0000, 0xffffff, (uintptr_t)IPL);
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
m68k_init();
return;
#elif defined (HAVE_CYCLONE)
m68k.read8 = read8;
m68k.read16 = read16;
m68k.read32 = cpu_readmem24_dword;
m68k.fetch8 = read8;
m68k.fetch16 = read16;
m68k.fetch32 = cpu_readmem24_dword;
m68k.write8 = cpu_writemem24;
m68k.write16 = cpu_writemem24_word;
m68k.write32 = cpu_writemem24_dword;
m68k.checkpc = MyCheckPc;
m68k.IrqCallback = my_irqh_callback;
CycloneInit();
#elif defined (HAVE_C68K)
C68k_Init(&C68K, my_irqh_callback);
C68k_Set_ReadB(&C68K, cpu_readmem24);
C68k_Set_ReadW(&C68K, cpu_readmem24_word);
C68k_Set_WriteB(&C68K, cpu_writemem24);
C68k_Set_WriteW(&C68K, cpu_writemem24_word);
C68k_Set_Fetch(&C68K, 0x000000, 0xbfffff, (uintptr_t)MEM);
C68k_Set_Fetch(&C68K, 0xc00000, 0xc7ffff, (uintptr_t)GVRAM);
C68k_Set_Fetch(&C68K, 0xe00000, 0xe7ffff, (uintptr_t)TVRAM);
C68k_Set_Fetch(&C68K, 0xea0000, 0xea1fff, (uintptr_t)SCSIIPL);
C68k_Set_Fetch(&C68K, 0xed0000, 0xed3fff, (uintptr_t)SRAM);
C68k_Set_Fetch(&C68K, 0xf00000, 0xfbffff, (uintptr_t)FONT);
C68k_Set_Fetch(&C68K, 0xfc0000, 0xffffff, (uintptr_t)IPL);
#elif defined (HAVE_MUSASHI)
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
m68k_init();
#endif /* HAVE_C68K */ /* HAVE_MUSASHI */
}
/*--------------------------------------------------------
CPU¥ê¥»¥Ã¥È
--------------------------------------------------------*/
void m68000_reset(void)
{
#ifdef HAVE_CPU_RUNTIME
if (m68000_use_musashi) m68k_pulse_reset(); else C68k_Reset(&C68K);
return;
#elif defined (HAVE_CYCLONE)
CycloneReset(&m68k);
m68k.state_flags = 0; /* Go to default state (not stopped, halted, etc.) */
m68k.srh = 0x27; /* Set supervisor mode */
#elif defined (HAVE_C68K)
C68k_Reset(&C68K);
#elif defined (HAVE_MUSASHI)
m68k_pulse_reset();
#endif /* HAVE_C68K */ /* HAVE_MUSASHI */
}
/*--------------------------------------------------------
CPUÄä»ß
--------------------------------------------------------*/
void m68000_exit(void)
{
}
/*--------------------------------------------------------
CPU¼Â¹Ô
--------------------------------------------------------*/
int m68000_execute(int cycles)
{
#ifdef HAVE_CPU_RUNTIME
return m68000_use_musashi ? m68k_execute(cycles) : C68k_Exec(&C68K, cycles);
#elif defined (HAVE_CYCLONE)
m68k.cycles = cycles;
CycloneRun(&m68k);
return m68k.cycles ;
#elif defined (HAVE_C68K)
return C68k_Exec(&C68K, cycles);
#elif defined (HAVE_MUSASHI)
return m68k_execute(cycles);
#endif /* HAVE_C68K */ /* HAVE_MUSASHI */
}
/*--------------------------------------------------------
³ä¤ê¹þ¤ß½èÍý
--------------------------------------------------------*/
void m68000_set_irq_line(int irqline, int state)
{
#ifdef HAVE_CPU_RUNTIME
(void)state;
if (m68000_use_musashi) m68k_set_irq((unsigned int)irqline);
else C68k_Set_IRQ(&C68K, (int32_t)irqline, irqline ? HOLD_LINE : CLEAR_LINE);
return;
#elif defined (HAVE_CYCLONE)
m68k.irq = irqline;
#elif defined (HAVE_C68K)
C68k_Set_IRQ(&C68K, irqline);
#elif defined (HAVE_MUSASHI)
m68k_set_irq(irqline);
#endif /* HAVE_C68K */ /* HAVE_MUSASHI */
}
/*--------------------------------------------------------
¥ì¥¸¥¹¥¿¼èÆÀ
--------------------------------------------------------*/
uint32_t m68000_get_reg(int regnum)
{
#ifdef HAVE_CPU_RUNTIME
if (m68000_use_musashi) {
switch (regnum) {
case M68K_PC: return m68k_get_reg(NULL, M68K_REG_PC);
case M68K_USP: return m68k_get_reg(NULL, M68K_REG_USP);
case M68K_MSP: return m68k_get_reg(NULL, M68K_REG_MSP);
case M68K_SR: return m68k_get_reg(NULL, M68K_REG_SR);
default:
if (regnum >= M68K_D0 && regnum <= M68K_D7) return m68k_get_reg(NULL, M68K_REG_D0 + regnum - M68K_D0);
if (regnum >= M68K_A0 && regnum <= M68K_A7) return m68k_get_reg(NULL, M68K_REG_A0 + regnum - M68K_A0);
return 0;
}
}
#endif
#if defined (HAVE_CYCLONE)
switch (regnum)
{
case M68K_PC: return m68k.pc - m68k.membase;
case M68K_SR: return CycloneGetSr(&m68k);
case M68K_D0: return m68k.d[0];
case M68K_D1: return m68k.d[1];
case M68K_D2: return m68k.d[2];
case M68K_D3: return m68k.d[3];
case M68K_D4: return m68k.d[4];
case M68K_D5: return m68k.d[5];
case M68K_D6: return m68k.d[6];
case M68K_D7: return m68k.d[7];
case M68K_A0: return m68k.a[0];
case M68K_A1: return m68k.a[1];
case M68K_A2: return m68k.a[2];
case M68K_A3: return m68k.a[3];
case M68K_A4: return m68k.a[4];
case M68K_A5: return m68k.a[5];
case M68K_A6: return m68k.a[6];
case M68K_A7: return m68k.a[7];
default:
break;
}
return 0x0BADC0DE;
#elif defined (HAVE_C68K) || defined (HAVE_CPU_RUNTIME)
switch (regnum)
{
case M68K_PC: return C68k_Get_Reg(&C68K, C68K_PC);
case M68K_USP: return C68k_Get_Reg(&C68K, C68K_USP);
case M68K_MSP: return C68k_Get_Reg(&C68K, C68K_MSP);
case M68K_SR: return C68k_Get_Reg(&C68K, C68K_SR);
case M68K_D0: return C68k_Get_Reg(&C68K, C68K_D0);
case M68K_D1: return C68k_Get_Reg(&C68K, C68K_D1);
case M68K_D2: return C68k_Get_Reg(&C68K, C68K_D2);
case M68K_D3: return C68k_Get_Reg(&C68K, C68K_D3);
case M68K_D4: return C68k_Get_Reg(&C68K, C68K_D4);
case M68K_D5: return C68k_Get_Reg(&C68K, C68K_D5);
case M68K_D6: return C68k_Get_Reg(&C68K, C68K_D6);
case M68K_D7: return C68k_Get_Reg(&C68K, C68K_D7);
case M68K_A0: return C68k_Get_Reg(&C68K, C68K_A0);
case M68K_A1: return C68k_Get_Reg(&C68K, C68K_A1);
case M68K_A2: return C68k_Get_Reg(&C68K, C68K_A2);
case M68K_A3: return C68k_Get_Reg(&C68K, C68K_A3);
case M68K_A4: return C68k_Get_Reg(&C68K, C68K_A4);
case M68K_A5: return C68k_Get_Reg(&C68K, C68K_A5);
case M68K_A6: return C68k_Get_Reg(&C68K, C68K_A6);
case M68K_A7: return C68k_Get_Reg(&C68K, C68K_A7);
default: return 0;
}
#elif defined (HAVE_MUSASHI)
switch (regnum)
{
case M68K_PC: return m68k_get_reg(NULL, M68K_REG_PC);
case M68K_USP: return m68k_get_reg(NULL, M68K_REG_USP);
case M68K_MSP: return m68k_get_reg(NULL, M68K_REG_MSP);
case M68K_SR: return m68k_get_reg(NULL, M68K_REG_SR);
case M68K_D0: return m68k_get_reg(NULL, M68K_REG_D0);
case M68K_D1: return m68k_get_reg(NULL, M68K_REG_D1);
case M68K_D2: return m68k_get_reg(NULL, M68K_REG_D2);
case M68K_D3: return m68k_get_reg(NULL, M68K_REG_D3);
case M68K_D4: return m68k_get_reg(NULL, M68K_REG_D4);
case M68K_D5: return m68k_get_reg(NULL, M68K_REG_D5);
case M68K_D6: return m68k_get_reg(NULL, M68K_REG_D6);
case M68K_D7: return m68k_get_reg(NULL, M68K_REG_D7);
case M68K_A0: return m68k_get_reg(NULL, M68K_REG_A0);
case M68K_A1: return m68k_get_reg(NULL, M68K_REG_A1);
case M68K_A2: return m68k_get_reg(NULL, M68K_REG_A2);
case M68K_A3: return m68k_get_reg(NULL, M68K_REG_A3);
case M68K_A4: return m68k_get_reg(NULL, M68K_REG_A4);
case M68K_A5: return m68k_get_reg(NULL, M68K_REG_A5);
case M68K_A6: return m68k_get_reg(NULL, M68K_REG_A6);
case M68K_A7: return m68k_get_reg(NULL, M68K_REG_A7);
default: return 0;
}
#endif /* HAVE_C68K */ /* HAVE_MUSASHI */
}
/*--------------------------------------------------------
¥ì¥¸¥¹¥¿ÀßÄê
--------------------------------------------------------*/
void m68000_set_reg(int regnum, uint32_t val)
{
#ifdef HAVE_CPU_RUNTIME
if (m68000_use_musashi) {
switch (regnum) {
case M68K_PC: m68k_set_reg(M68K_REG_PC, val); break;
case M68K_USP: m68k_set_reg(M68K_REG_USP, val); break;
case M68K_MSP: m68k_set_reg(M68K_REG_MSP, val); break;
case M68K_SR: m68k_set_reg(M68K_REG_SR, val); break;
default:
if (regnum >= M68K_D0 && regnum <= M68K_D7) m68k_set_reg(M68K_REG_D0 + regnum - M68K_D0, val);
else if (regnum >= M68K_A0 && regnum <= M68K_A7) m68k_set_reg(M68K_REG_A0 + regnum - M68K_A0, val);
break;
}
return;
}
#endif
#if defined (HAVE_CYCLONE)
switch (regnum)
{
case M68K_PC:
m68k.pc = m68k.checkpc(val+m68k.membase);
break;
case M68K_SR:
CycloneSetSr(&m68k, val);
break;
case M68K_D0: m68k.d[0] = val; break;
case M68K_D1: m68k.d[1] = val; break;
case M68K_D2: m68k.d[2] = val; break;
case M68K_D3: m68k.d[3] = val; break;
case M68K_D4: m68k.d[4] = val; break;
case M68K_D5: m68k.d[5] = val; break;
case M68K_D6: m68k.d[6] = val; break;
case M68K_D7: m68k.d[7] = val; break;
case M68K_A0: m68k.a[0] = val; break;
case M68K_A1: m68k.a[1] = val; break;
case M68K_A2: m68k.a[2] = val; break;
case M68K_A3: m68k.a[3] = val; break;
case M68K_A4: m68k.a[4] = val; break;
case M68K_A5: m68k.a[5] = val; break;
case M68K_A6: m68k.a[6] = val; break;
case M68K_A7: m68k.a[7] = val; break;
default: break;
}
#elif defined (HAVE_C68K) || defined (HAVE_CPU_RUNTIME)
switch (regnum)
{
case M68K_PC: C68k_Set_Reg(&C68K, C68K_PC, val); break;
case M68K_USP: C68k_Set_Reg(&C68K, C68K_USP, val); break;
case M68K_MSP: C68k_Set_Reg(&C68K, C68K_MSP, val); break;
case M68K_SR: C68k_Set_Reg(&C68K, C68K_SR, val); break;
case M68K_D0: C68k_Set_Reg(&C68K, C68K_D0, val); break;
case M68K_D1: C68k_Set_Reg(&C68K, C68K_D1, val); break;
case M68K_D2: C68k_Set_Reg(&C68K, C68K_D2, val); break;
case M68K_D3: C68k_Set_Reg(&C68K, C68K_D3, val); break;
case M68K_D4: C68k_Set_Reg(&C68K, C68K_D4, val); break;
case M68K_D5: C68k_Set_Reg(&C68K, C68K_D5, val); break;
case M68K_D6: C68k_Set_Reg(&C68K, C68K_D6, val); break;
case M68K_D7: C68k_Set_Reg(&C68K, C68K_D7, val); break;
case M68K_A0: C68k_Set_Reg(&C68K, C68K_A0, val); break;
case M68K_A1: C68k_Set_Reg(&C68K, C68K_A1, val); break;
case M68K_A2: C68k_Set_Reg(&C68K, C68K_A2, val); break;
case M68K_A3: C68k_Set_Reg(&C68K, C68K_A3, val); break;
case M68K_A4: C68k_Set_Reg(&C68K, C68K_A4, val); break;
case M68K_A5: C68k_Set_Reg(&C68K, C68K_A5, val); break;
case M68K_A6: C68k_Set_Reg(&C68K, C68K_A6, val); break;
case M68K_A7: C68k_Set_Reg(&C68K, C68K_A7, val); break;
default: break;
}
#elif defined (HAVE_MUSASHI)
switch (regnum)
{
case M68K_PC: m68k_set_reg(M68K_REG_PC, val); break;
case M68K_USP: m68k_set_reg(M68K_REG_USP, val); break;
case M68K_MSP: m68k_set_reg(M68K_REG_MSP, val); break;
case M68K_SR: m68k_set_reg(M68K_REG_SR, val); break;
case M68K_D0: m68k_set_reg(M68K_REG_D0, val); break;
case M68K_D1: m68k_set_reg(M68K_REG_D1, val); break;
case M68K_D2: m68k_set_reg(M68K_REG_D2, val); break;
case M68K_D3: m68k_set_reg(M68K_REG_D3, val); break;
case M68K_D4: m68k_set_reg(M68K_REG_D4, val); break;
case M68K_D5: m68k_set_reg(M68K_REG_D5, val); break;
case M68K_D6: m68k_set_reg(M68K_REG_D6, val); break;
case M68K_D7: m68k_set_reg(M68K_REG_D7, val); break;
case M68K_A0: m68k_set_reg(M68K_REG_A0, val); break;
case M68K_A1: m68k_set_reg(M68K_REG_A1, val); break;
case M68K_A2: m68k_set_reg(M68K_REG_A2, val); break;
case M68K_A3: m68k_set_reg(M68K_REG_A3, val); break;
case M68K_A4: m68k_set_reg(M68K_REG_A4, val); break;
case M68K_A5: m68k_set_reg(M68K_REG_A5, val); break;
case M68K_A6: m68k_set_reg(M68K_REG_A6, val); break;
case M68K_A7: m68k_set_reg(M68K_REG_A7, val); break;
default: break;
}
#endif /* HAVE_C68K */ /* HAVE_MUSASHI */
}
/*------------------------------------------------------
¥»¡¼¥Ö/¥í¡¼¥É ¥¹¥Æ¡¼¥È
------------------------------------------------------*/
#ifdef SAVE_STATE
STATE_SAVE( m68000 )
{
#if defined (HAVE_CYCLONE)
/* empty */
#elif defined (HAVE_C68K)
int i;
uint32_t pc = C68k_Get_Reg(&C68K, C68K_PC);
for (i = 0; i < 8; i++)
state_save_long(&C68K.D[i], 1);
for (i = 0; i < 8; i++)
state_save_long(&C68K.A[i], 1);
state_save_long(&C68K.flag_C, 1);
state_save_long(&C68K.flag_V, 1);
state_save_long(&C68K.flag_Z, 1);
state_save_long(&C68K.flag_N, 1);
state_save_long(&C68K.flag_X, 1);
state_save_long(&C68K.flag_I, 1);
state_save_long(&C68K.flag_S, 1);
state_save_long(&C68K.USP, 1);
state_save_long(&pc, 1);
state_save_long(&C68K.HaltState, 1);
state_save_long(&C68K.IRQLine, 1);
state_save_long(&C68K.IRQState, 1);
#endif /* HAVE_C68K */
}
STATE_LOAD( m68000 )
{
#if defined (HAVE_CYCLONE)
/* empty */
#elif defined (HAVE_C68K)
int i;
uint32_t pc;
for (i = 0; i < 8; i++)
state_load_long(&C68K.D[i], 1);
for (i = 0; i < 8; i++)
state_load_long(&C68K.A[i], 1);
state_load_long(&C68K.flag_C, 1);
state_load_long(&C68K.flag_V, 1);
state_load_long(&C68K.flag_Z, 1);
state_load_long(&C68K.flag_N, 1);
state_load_long(&C68K.flag_X, 1);
state_load_long(&C68K.flag_I, 1);
state_load_long(&C68K.flag_S, 1);
state_load_long(&C68K.USP, 1);
state_load_long(&pc, 1);
state_load_long(&C68K.HaltState, 1);
state_load_long(&C68K.IRQLine, 1);
state_load_long(&C68K.IRQState, 1);
C68k_Set_Reg(&C68K, C68K_PC, pc);
#endif /* HAVE_C68K */
}
#endif /* SAVE_STATE */