--- uae/src/newcpu.c 2018/04/24 16:56:39 1.1.1.12 +++ uae/src/newcpu.c 2018/04/24 17:05:38 1.1.1.17 @@ -21,6 +21,7 @@ #include "debug.h" #include "compiler.h" #include "gui.h" +#include "savestate.h" /* Opcode of faulting instruction */ uae_u16 last_op_for_exception_3; @@ -674,7 +675,9 @@ void MakeFromSR (void) if (regs.t1 || regs.t0) set_special (SPCFLAG_TRACE); else - unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE); + /* Keep SPCFLAG_DOTRACE, we still want a trace exception for + SR-modifying instructions (including STOP). */ + unset_special (SPCFLAG_TRACE); } void Exception(int nr, uaecptr oldpc) @@ -747,7 +750,7 @@ kludge_me_do: unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE); } -static void Interrupt(int nr) +static void Interrupt (int nr) { assert(nr < 8 && nr >= 0); lastint_regs = regs; @@ -758,7 +761,7 @@ static void Interrupt(int nr) set_special (SPCFLAG_INT); } -static uae_u32 caar, cacr, itt0, itt1, dtt0, dtt1, tc, mmusr; +static uae_u32 caar, cacr, itt0, itt1, dtt0, dtt1, tc, mmusr, urp, srp; int m68k_move2c (int regno, uae_u32 *regp) { @@ -774,7 +777,7 @@ int m68k_move2c (int regno, uae_u32 *reg case 1: regs.dfc = *regp & 7; break; case 2: cacr = *regp & (currprefs.cpu_level < 4 ? 0x3 : 0x80008000); break; case 3: tc = *regp & 0xc000; break; - /* Mask out fields that should be zero. */ + /* Mask out fields that should be zero. */ case 4: itt0 = *regp & 0xffffe364; break; case 5: itt1 = *regp & 0xffffe364; break; case 6: dtt0 = *regp & 0xffffe364; break; @@ -785,6 +788,9 @@ int m68k_move2c (int regno, uae_u32 *reg case 0x802: caar = *regp & 0xfc; break; case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break; case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break; + case 0x805: mmusr = *regp; break; + case 0x806: urp = *regp; break; + case 0x807: srp = *regp; break; default: op_illg (0x4E7B); return 0; @@ -817,6 +823,8 @@ int m68k_movec2 (int regno, uae_u32 *reg case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break; case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break; case 0x805: *regp = mmusr; break; + case 0x806: *regp = urp; break; + case 0x807: *regp = srp; break; default: op_illg (0x4E7A); return 0; @@ -1082,10 +1090,25 @@ static char* ccnames[] = void m68k_reset (void) { + regs.kick_mask = 0x00F80000; + regs.spcflags = 0; + if (savestate_state == STATE_RESTORE) { + m68k_setpc (regs.pc); + /* MakeFromSR() must not swap stack pointer */ + regs.s = (regs.sr >> 13) & 1; + MakeFromSR(); + /* set stack pointer */ + if (regs.s) + m68k_areg(regs, 7) = regs.isp; + else + m68k_areg(regs, 7) = regs.usp; + return; + } + m68k_areg (regs, 7) = get_long (0x00f80000); m68k_setpc (get_long (0x00f80004)); + refill_prefetch (m68k_getpc (), 0); fill_prefetch_0 (); - regs.kick_mask = 0xF80000; regs.s = 1; regs.m = 0; regs.stopped = 0; @@ -1096,7 +1119,6 @@ void m68k_reset (void) SET_CFLG (0); SET_VFLG (0); SET_NFLG (0); - regs.spcflags = 0; regs.intmask = 7; regs.vbr = regs.sfc = regs.dfc = 0; regs.fpcr = regs.fpsr = regs.fpiar = 0; @@ -1128,14 +1150,14 @@ unsigned long REGPARAM2 op_illg (uae_u32 ersatz_perform (arg); fill_prefetch_0 (); return 4; - } else if ((pc & 0xF80000) == 0xF00000) { + } else if ((pc & 0xFFFF0000) == RTAREA_BASE) { /* User-mode STOP replacement */ m68k_setstopped (1); return 4; } } - if ((opcode & 0xF000) == 0xA000 && (pc & 0xF80000) == 0xF00000) { + if ((opcode & 0xF000) == 0xA000 && (pc & 0xFFFF0000) == RTAREA_BASE) { /* Calltrap. */ m68k_incpc(2); call_calltrap (opcode & 0xFFF); @@ -1148,7 +1170,7 @@ unsigned long REGPARAM2 op_illg (uae_u32 return 4; } if ((opcode & 0xF000) == 0xA000) { - if ((pc & 0xF80000) == 0xF00000) { + if ((pc & 0xFFFF0000) == RTAREA_BASE) { /* Calltrap. */ call_calltrap (opcode & 0xFFF); } @@ -1222,7 +1244,7 @@ static int do_specialties (void) /*n_spcinsns++;*/ while (regs.spcflags & SPCFLAG_BLTNASTY) { - do_cycles (4); + do_cycles (4 * CYCLE_UNIT); if (regs.spcflags & SPCFLAG_COPPER) do_copper (); } @@ -1232,7 +1254,7 @@ static int do_specialties (void) Exception (9,last_trace_ad); } while (regs.spcflags & SPCFLAG_STOP) { - do_cycles (4); + do_cycles (4 * CYCLE_UNIT); if (regs.spcflags & SPCFLAG_COPPER) do_copper (); if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)){ @@ -1280,7 +1302,7 @@ static void m68k_run_1 (void) uae_u32 opcode = get_iword_prefetch (0); #ifdef DEBUG_PREFETCH if (get_ilong (0) != do_get_mem_long (®s.prefetch)) { - fprintf (stderr, "Prefetch differs from memory.\n"); + write_log ("Prefetch differs from memory.\n"); debugging = 1; return; } @@ -1305,7 +1327,7 @@ static void m68k_run_1 (void) #endif #ifdef DEBUG_PREFETCH if (memcmp (saved_bytes, oldpcp, 20) != 0) { - fprintf (stderr, "Self-modifying code detected.\n"); + write_log ("Self-modifying code detected.\n"); set_special (SPCFLAG_BRK); debugging = 1; } @@ -1366,7 +1388,7 @@ STATIC_INLINE void m68k_run1 (void (*fun : : "r" (func) : "%eax", "%edx", "%ecx", "memory", "cc"); } #else -#define m68k_run1(F) F() +#define m68k_run1(F) (F) () #endif int in_m68k_go = 0; @@ -1390,7 +1412,11 @@ void m68k_go (int may_quit) m68k_reset (); reset_all_systems (); customreset (); + /* We may have been restoring state, but we're done now. */ + savestate_restore_finish (); + handle_active_events (); } + if (debugging) debug (); m68k_run1 (currprefs.cpu_compatible ? m68k_run_1 : m68k_run_2); @@ -1520,3 +1546,95 @@ void m68k_dumpstate (FILE *f, uaecptr *n if (nextpc) fprintf (f, "next PC: %08lx\n", *nextpc); } + + +/* CPU save/restore code */ + +#define CPUTYPE_EC 1 +#define CPUMODE_HALT 1 + +uae_u8 *restore_cpu (uae_u8 *src) +{ + int i,model,flags; + uae_u32 l; + + model = restore_u32(); + switch (model) { + case 68000: + currprefs.cpu_level = 0; + break; + case 68010: + currprefs.cpu_level = 1; + break; + case 68020: + currprefs.cpu_level = 2; + break; + default: + write_log ("Unknown cpu type %d\n", model); + break; + } + + flags = restore_u32(); + currprefs.address_space_24 = 0; + if (flags & CPUTYPE_EC) + currprefs.address_space_24 = 1; + for (i = 0; i < 15; i++) + regs.regs[i] = restore_u32 (); + regs.pc = restore_u32 (); + regs.prefetch = restore_u32 (); + regs.usp = restore_u32 (); + regs.isp = restore_u32 (); + regs.sr = restore_u16 (); + l = restore_u32(); + if (l & CPUMODE_HALT) + regs.stopped = 1; + else + regs.stopped = 0; + if (model >= 68010) { + regs.dfc = restore_u32 (); + regs.sfc = restore_u32 (); + regs.vbr = restore_u32 (); + } + if (model >= 68020) { + caar = restore_u32 (); + cacr = restore_u32 (); + regs.msp = restore_u32 (); + } + write_log ("CPU %d%s%03d, PC=%08.8X\n", + model/1000, flags & 1 ? "EC" : "", model % 1000, regs.pc); + + return src; +} + +static int cpumodel[] = { 68000, 68010, 68020, 68020 }; + +uae_u8 *save_cpu (int *len) +{ + uae_u8 *dstbak,*dst; + int model,i; + + dstbak = dst = malloc(4+4+15*4+4+4+4+4+2+4+4+4+4+4+4+4); + model = cpumodel[currprefs.cpu_level]; + save_u32 (model); /* MODEL */ + save_u32 (currprefs.address_space_24 ? 1 : 0); /* FLAGS */ + for(i = 0;i < 15; i++) save_u32 (regs.regs[i]); /* D0-D7 A0-A6 */ + save_u32 (m68k_getpc ()); /* PC */ + save_u32 (regs.prefetch); /* prefetch */ + MakeSR (); + save_u32 (!regs.s ? regs.regs[15] : regs.usp); /* USP */ + save_u32 (regs.s ? regs.regs[15] : regs.isp); /* ISP */ + save_u16 (regs.sr); /* SR/CCR */ + save_u32 (regs.stopped ? CPUMODE_HALT : 0); /* flags */ + if(model >= 68010) { + save_u32 (regs.dfc); /* DFC */ + save_u32 (regs.sfc); /* SFC */ + save_u32 (regs.vbr); /* VBR */ + } + if(model >= 68020) { + save_u32 (caar); /* CAAR */ + save_u32 (cacr); /* CACR */ + save_u32 (regs.msp); /* MSP */ + } + *len = dst - dstbak; + return dstbak; +}