--- uae/src/newcpu.c 2018/04/24 16:47:25 1.1.1.7 +++ uae/src/newcpu.c 2018/04/24 17:00:08 1.1.1.14 @@ -15,13 +15,13 @@ #include "uae.h" #include "memory.h" #include "custom.h" -#include "readcpu.h" #include "newcpu.h" #include "autoconf.h" #include "ersatz.h" #include "debug.h" #include "compiler.h" #include "gui.h" +#include "savestate.h" /* Opcode of faulting instruction */ uae_u16 last_op_for_exception_3; @@ -97,20 +97,11 @@ void dump_counts (void) int broken_in; -static __inline__ unsigned int cft_map (unsigned int f) -{ -#ifndef HAVE_GET_WORD_UNSWAPPED - return f; -#else - return ((f >> 8) & 255) | ((f & 255) << 8); -#endif -} - static unsigned long op_illg_1 (uae_u32 opcode) REGPARAM; static unsigned long REGPARAM2 op_illg_1 (uae_u32 opcode) { - op_illg (cft_map (opcode)); + op_illg (opcode); return 4; } @@ -118,20 +109,21 @@ static void build_cpufunctbl (void) { int i; unsigned long opcode; - struct cputbl *tbl = (currprefs.cpu_level == 3 ? op_smalltbl_0 - : currprefs.cpu_level == 2 ? op_smalltbl_1 - : currprefs.cpu_level == 1 ? op_smalltbl_2 - : currprefs.cpu_compatible ? op_smalltbl_4 - : op_smalltbl_3); + struct cputbl *tbl = (currprefs.cpu_level == 4 ? op_smalltbl_0_ff + : currprefs.cpu_level == 3 ? op_smalltbl_1_ff + : currprefs.cpu_level == 2 ? op_smalltbl_2_ff + : currprefs.cpu_level == 1 ? op_smalltbl_3_ff + : ! currprefs.cpu_compatible ? op_smalltbl_4_ff + : op_smalltbl_5_ff); write_log ("Building CPU function table (%d %d %d).\n", currprefs.cpu_level, currprefs.cpu_compatible, currprefs.address_space_24); for (opcode = 0; opcode < 65536; opcode++) - cpufunctbl[cft_map (opcode)] = op_illg_1; + cpufunctbl[opcode] = op_illg_1; for (i = 0; tbl[i].handler != NULL; i++) { if (! tbl[i].specific) - cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler; + cpufunctbl[tbl[i].opcode] = tbl[i].handler; } for (opcode = 0; opcode < 65536; opcode++) { cpuop_func *f; @@ -140,15 +132,15 @@ static void build_cpufunctbl (void) continue; if (table68k[opcode].handler != -1) { - f = cpufunctbl[cft_map (table68k[opcode].handler)]; + f = cpufunctbl[table68k[opcode].handler]; if (f == op_illg_1) abort(); - cpufunctbl[cft_map (opcode)] = f; + cpufunctbl[opcode] = f; } } for (i = 0; tbl[i].handler != NULL; i++) { if (tbl[i].specific) - cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler; + cpufunctbl[tbl[i].opcode] = tbl[i].handler; } } @@ -199,8 +191,8 @@ void init_m68k (void) for (j = 7 ; j >= 0 ; j--) { if (i & (1 << j)) break; } - fpp_movem_index1[i] = j; - fpp_movem_index2[i] = 7-j; + fpp_movem_index1[i] = 7-j; + fpp_movem_index2[i] = j; fpp_movem_next[i] = i & (~(1 << j)); } #if COUNT_INSTRS @@ -223,16 +215,20 @@ void init_m68k (void) if (currprefs.address_space_24 && currprefs.cpu_level > 1) write_log ("EC"); switch (currprefs.cpu_level) { - case 1: + case 1: write_log ("010"); break; - case 2: + case 2: write_log ("020"); break; - case 3: + case 3: write_log ("020/881"); break; - default: + case 4: + /* Who is going to miss the MMU anyway...? :-) */ + write_log ("040"); + break; + default: write_log ("000"); break; } @@ -258,7 +254,7 @@ int lastint_no; #define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) #define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o)) -uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf) +uae_s32 ShowEA (FILE *f, int reg, amodes mode, wordsizes size, char *buf) { uae_u16 dp; uae_s8 disp8; @@ -289,7 +285,7 @@ uae_s32 ShowEA (int reg, amodes mode, wo disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; addr = m68k_areg(regs,reg) + (uae_s16)disp16; sprintf (buffer,"(A%d,$%04x) == $%08lx", reg, disp16 & 0xffff, - (long unsigned int)addr); + (unsigned long)addr); break; case Ad8r: dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; @@ -322,20 +318,20 @@ uae_s32 ShowEA (int reg, amodes mode, wo dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3), disp,outer, - (long unsigned int)addr); + (unsigned long)addr); } else { addr = m68k_areg(regs,reg) + (uae_s32)((uae_s8)disp8) + dispreg; sprintf (buffer,"(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg, dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3), disp8, - (long unsigned int)addr); + (unsigned long)addr); } break; case PC16: addr = m68k_getpc () + m68kpc_offset; disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; addr += (uae_s16)disp16; - sprintf (buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(long unsigned int)addr); + sprintf (buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(unsigned long)addr); break; case PC8r: addr = m68k_getpc () + m68kpc_offset; @@ -369,20 +365,20 @@ uae_s32 ShowEA (int reg, amodes mode, wo dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3), disp,outer, - (long unsigned int)addr); + (unsigned long)addr); } else { addr += (uae_s32)((uae_s8)disp8) + dispreg; sprintf (buffer,"(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3), - disp8, (long unsigned int)addr); + disp8, (unsigned long)addr); } break; case absw: - sprintf (buffer,"$%08lx", (long unsigned int)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset)); + sprintf (buffer,"$%08lx", (unsigned long)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset)); m68kpc_offset += 2; break; case absl: - sprintf (buffer,"$%08lx", (long unsigned int)get_ilong_1 (m68kpc_offset)); + sprintf (buffer,"$%08lx", (unsigned long)get_ilong_1 (m68kpc_offset)); m68kpc_offset += 4; break; case imm: @@ -396,7 +392,7 @@ uae_s32 ShowEA (int reg, amodes mode, wo m68kpc_offset += 2; break; case sz_long: - sprintf (buffer,"#$%08lx", (long unsigned int)(get_ilong_1 (m68kpc_offset))); + sprintf (buffer,"#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset))); m68kpc_offset += 4; break; default: @@ -416,17 +412,17 @@ uae_s32 ShowEA (int reg, amodes mode, wo case imm2: offset = (uae_s32)get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; - sprintf (buffer,"#$%08lx", (long unsigned int)offset); + sprintf (buffer,"#$%08lx", (unsigned long)offset); break; case immi: offset = (uae_s32)(uae_s8)(reg & 0xff); - sprintf (buffer,"#$%08lx", (long unsigned int)offset); + sprintf (buffer,"#$%08lx", (unsigned long)offset); break; default: break; } if (buf == 0) - printf ("%s", buffer); + fprintf (f, "%s", buffer); else strcat (buf, buffer); return offset; @@ -675,17 +671,20 @@ void MakeFromSR (void) } } - regs.spcflags |= SPCFLAG_INT; + set_special (SPCFLAG_INT); if (regs.t1 || regs.t0) - regs.spcflags |= SPCFLAG_TRACE; + set_special (SPCFLAG_TRACE); else - regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE); + unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE); } void Exception(int nr, uaecptr oldpc) { + uae_u32 currpc = m68k_getpc (); + compiler_flush_jsr_stack(); MakeSR(); + if (!regs.s) { regs.usp = m68k_areg(regs, 7); if (currprefs.cpu_level >= 2) @@ -713,7 +712,7 @@ void Exception(int nr, uaecptr oldpc) m68k_areg(regs, 7) -= 2; put_word (m68k_areg(regs, 7), nr * 4); m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), m68k_getpc ()); + put_long (m68k_areg(regs, 7), currpc); m68k_areg(regs, 7) -= 2; put_word (m68k_areg(regs, 7), regs.sr); regs.sr |= (1 << 13); @@ -739,14 +738,14 @@ void Exception(int nr, uaecptr oldpc) } } m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), m68k_getpc ()); + put_long (m68k_areg(regs, 7), currpc); kludge_me_do: m68k_areg(regs, 7) -= 2; put_word (m68k_areg(regs, 7), regs.sr); m68k_setpc (get_long (regs.vbr + 4*nr)); fill_prefetch_0 (); regs.t1 = regs.t0 = regs.m = 0; - regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE); + unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE); } static void Interrupt(int nr) @@ -757,52 +756,77 @@ static void Interrupt(int nr) Exception(nr+24, 0); regs.intmask = nr; - regs.spcflags |= SPCFLAG_INT; + set_special (SPCFLAG_INT); } -static int caar, cacr; +static uae_u32 caar, cacr, itt0, itt1, dtt0, dtt1, tc, mmusr; -void m68k_move2c (int regno, uae_u32 *regp) +int m68k_move2c (int regno, uae_u32 *regp) { - if (currprefs.cpu_level == 1 && (regno & 0x7FF) > 1) + if ((currprefs.cpu_level == 1 && (regno & 0x7FF) > 1) + || (currprefs.cpu_level < 4 && (regno & 0x7FF) > 2) + || (currprefs.cpu_level == 4 && regno == 0x802)) + { op_illg (0x4E7B); - else + return 0; + } else { switch (regno) { - case 0: regs.sfc = *regp & 7; break; - case 1: regs.dfc = *regp & 7; break; - case 2: cacr = *regp & 0x3; break; /* ignore C and CE */ - case 0x800: regs.usp = *regp; break; - case 0x801: regs.vbr = *regp; break; - 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; - default: + case 0: regs.sfc = *regp & 7; break; + 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. */ + case 4: itt0 = *regp & 0xffffe364; break; + case 5: itt1 = *regp & 0xffffe364; break; + case 6: dtt0 = *regp & 0xffffe364; break; + case 7: dtt1 = *regp & 0xffffe364; break; + + case 0x800: regs.usp = *regp; break; + case 0x801: regs.vbr = *regp; break; + 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; + default: op_illg (0x4E7B); - break; + return 0; } + } + return 1; } -void m68k_movec2 (int regno, uae_u32 *regp) +int m68k_movec2 (int regno, uae_u32 *regp) { - if (currprefs.cpu_level == 1 && (regno & 0x7FF) > 1) + if ((currprefs.cpu_level == 1 && (regno & 0x7FF) > 1) + || (currprefs.cpu_level < 4 && (regno & 0x7FF) > 2) + || (currprefs.cpu_level == 4 && regno == 0x802)) + { op_illg (0x4E7A); - else + return 0; + } else { switch (regno) { - case 0: *regp = regs.sfc; break; - case 1: *regp = regs.dfc; break; - case 2: *regp = cacr; break; - case 0x800: *regp = regs.usp; break; - case 0x801: *regp = regs.vbr; break; - case 0x802: *regp = caar; break; - 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; - default: + case 0: *regp = regs.sfc; break; + case 1: *regp = regs.dfc; break; + case 2: *regp = cacr; break; + case 3: *regp = tc; break; + case 4: *regp = itt0; break; + case 5: *regp = itt1; break; + case 6: *regp = dtt0; break; + case 7: *regp = dtt1; break; + case 0x800: *regp = regs.usp; break; + case 0x801: *regp = regs.vbr; break; + case 0x802: *regp = caar; break; + 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; + default: op_illg (0x4E7A); - break; + return 0; } + } + return 1; } -static __inline__ int +STATIC_INLINE int div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem) { uae_u32 q = 0, cbit = 0; @@ -948,7 +972,7 @@ void m68k_divl (uae_u32 opcode, uae_u32 #endif } -static __inline__ void +STATIC_INLINE void mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo) { uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff); @@ -1059,10 +1083,24 @@ 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)); fill_prefetch_0 (); - regs.kick_mask = 0xF80000; regs.s = 1; regs.m = 0; regs.stopped = 0; @@ -1073,7 +1111,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; @@ -1094,7 +1131,7 @@ unsigned long REGPARAM2 op_illg (uae_u32 if (opcode == 0x4E7B && get_long (0x10) == 0 && (pc & 0xF80000) == 0xF80000) { write_log ("Your Kickstart requires a 68020 CPU. Giving up.\n"); broken_in = 1; - regs.spcflags |= SPCFLAG_BRK; + set_special (SPCFLAG_BRK); quit_program = 1; } if (opcode == 0xFF0D) { @@ -1132,17 +1169,22 @@ unsigned long REGPARAM2 op_illg (uae_u32 Exception(0xA,0); return 4; } +#if 1 write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc); +#endif Exception (4,0); return 4; } void mmu_op(uae_u32 opcode, uae_u16 extra) { - if ((extra & 0xB000) == 0) { /* PMOVE instruction */ - - } else if ((extra & 0xF000) == 0x2000) { /* PLOAD instruction */ - } else if ((extra & 0xF000) == 0x8000) { /* PTEST instruction */ + if ((opcode & 0xFE0) == 0x0500) { + /* PFLUSH */ + mmusr = 0; + write_log ("PFLUSH\n"); + } else if ((opcode & 0x0FD8) == 0x548) { + /* PTEST */ + write_log ("PTEST\n"); } else op_illg (opcode); } @@ -1153,7 +1195,7 @@ static uaecptr last_trace_ad = 0; static void do_trace (void) { - if (regs.t0) { + if (regs.t0 && currprefs.cpu_level >= 2) { uae_u16 opcode; /* should also include TRAP, CHK, SR modification FPcc */ /* probably never used so why bother */ @@ -1176,88 +1218,98 @@ static void do_trace (void) && (uae_s16)m68k_dreg(regs, opcode & 7) != 0)) { last_trace_ad = m68k_getpc (); - regs.spcflags &= ~SPCFLAG_TRACE; - regs.spcflags |= SPCFLAG_DOTRACE; + unset_special (SPCFLAG_TRACE); + set_special (SPCFLAG_DOTRACE); } } else if (regs.t1) { last_trace_ad = m68k_getpc (); - regs.spcflags &= ~SPCFLAG_TRACE; - regs.spcflags |= SPCFLAG_DOTRACE; + unset_special (SPCFLAG_TRACE); + set_special (SPCFLAG_DOTRACE); } } static int do_specialties (void) { + if (regs.spcflags & SPCFLAG_COPPER) + do_copper (); + /*n_spcinsns++;*/ while (regs.spcflags & SPCFLAG_BLTNASTY) { - do_cycles (4); - if (regs.spcflags & SPCFLAG_DISK) - do_disk (); + do_cycles (4 * CYCLE_UNIT); + if (regs.spcflags & SPCFLAG_COPPER) + do_copper (); } + run_compiled_code(); if (regs.spcflags & SPCFLAG_DOTRACE) { Exception (9,last_trace_ad); } while (regs.spcflags & SPCFLAG_STOP) { - do_cycles (4); - if (regs.spcflags & SPCFLAG_DISK) - do_disk (); + do_cycles (4 * CYCLE_UNIT); + if (regs.spcflags & SPCFLAG_COPPER) + do_copper (); if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)){ int intr = intlev (); - regs.spcflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT); + unset_special (SPCFLAG_INT | SPCFLAG_DOINT); if (intr != -1 && intr > regs.intmask) { Interrupt (intr); regs.stopped = 0; - regs.spcflags &= ~SPCFLAG_STOP; + unset_special (SPCFLAG_STOP); } } } if (regs.spcflags & SPCFLAG_TRACE) do_trace (); - if (regs.spcflags & SPCFLAG_DISK) - do_disk (); - if (regs.spcflags & SPCFLAG_DOINT) { int intr = intlev (); - regs.spcflags &= ~SPCFLAG_DOINT; + unset_special (SPCFLAG_DOINT); if (intr != -1 && intr > regs.intmask) { Interrupt (intr); regs.stopped = 0; } } if (regs.spcflags & SPCFLAG_INT) { - regs.spcflags &= ~SPCFLAG_INT; - regs.spcflags |= SPCFLAG_DOINT; + unset_special (SPCFLAG_INT); + set_special (SPCFLAG_DOINT); } if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) { - regs.spcflags &= ~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); + unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE); return 1; } return 0; } +/* It's really sad to have two almost identical functions for this, but we + do it all for performance... :( */ static void m68k_run_1 (void) { +#ifdef DEBUG_PREFETCH + uae_u8 saved_bytes[20]; + uae_u16 *oldpcp; +#endif for (;;) { int cycles; - uae_u32 opcode = GET_OPCODE; -#if 0 + 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"); debugging = 1; return; } + oldpcp = regs.pc_p; + memcpy (saved_bytes, regs.pc_p, 20); #endif /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */ /* regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/ #if COUNT_INSTRS == 2 - if (table68k[cft_map (opcode)].handler != -1) - instrcount[table68k[cft_map (opcode)].handler]++; + if (table68k[opcode].handler != -1) + instrcount[table68k[opcode].handler]++; #elif COUNT_INSTRS == 1 instrcount[opcode]++; #endif -#if defined(X86_ASSEMBLY) +#if defined X86_ASSEMBLY __asm__ __volatile__("\tcall *%%ebx" : "=&a" (cycles) : "b" (cpufunctbl[opcode]), "0" (opcode) : "%edx", "%ecx", @@ -1265,6 +1317,50 @@ static void m68k_run_1 (void) #else cycles = (*cpufunctbl[opcode])(opcode); #endif +#ifdef DEBUG_PREFETCH + if (memcmp (saved_bytes, oldpcp, 20) != 0) { + fprintf (stderr, "Self-modifying code detected.\n"); + set_special (SPCFLAG_BRK); + debugging = 1; + } +#endif + /*n_insns++;*/ + cycles &= cycles_mask; + cycles |= cycles_val; + do_cycles (cycles); + if (regs.spcflags) { + if (do_specialties ()) + return; + } + } +} + +#define DEBUG_PREFETCH + +/* Same thing, but don't use prefetch to get opcode. */ +static void m68k_run_2 (void) +{ + for (;;) { + int cycles; + uae_u32 opcode = get_iword (0); + + /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */ +/* regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/ +#if COUNT_INSTRS == 2 + if (table68k[opcode].handler != -1) + instrcount[table68k[opcode].handler]++; +#elif COUNT_INSTRS == 1 + instrcount[opcode]++; +#endif +#if defined X86_ASSEMBLY + __asm__ __volatile__("\tcall *%%ebx" + : "=&a" (cycles) : "b" (cpufunctbl[opcode]), "0" (opcode) + : "%edx", "%ecx", + "%esi", "%edi", "%ebp", "memory", "cc"); +#else + cycles = (*cpufunctbl[opcode])(opcode); +#endif + /*n_insns++;*/ cycles &= cycles_mask; cycles |= cycles_val; @@ -1277,13 +1373,14 @@ static void m68k_run_1 (void) } #ifdef X86_ASSEMBLY -static __inline__ void m68k_run1 (void) +STATIC_INLINE void m68k_run1 (void (*func)(void)) { /* Work around compiler bug: GCC doesn't push %ebp in m68k_run_1. */ - __asm__ __volatile__ ("pushl %%ebp\n\tcall *%0\n\tpopl %%ebp" : : "r" (m68k_run_1) : "%eax", "%edx", "%ecx", "memory", "cc"); + __asm__ __volatile__ ("pushl %%ebp\n\tcall *%0\n\tpopl %%ebp" + : : "r" (func) : "%eax", "%edx", "%ecx", "memory", "cc"); } #else -#define m68k_run1 m68k_run_1 +#define m68k_run1(F) (F) () #endif int in_m68k_go = 0; @@ -1307,10 +1404,14 @@ 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 (); + m68k_run1 (currprefs.cpu_compatible ? m68k_run_1 : m68k_run_2); } in_m68k_go--; } @@ -1324,7 +1425,7 @@ static void m68k_verify (uaecptr addr, u last_op_for_exception_3 = opcode; m68kpc_offset = 2; - if (cpufunctbl[cft_map (opcode)] == op_illg_1) { + if (cpufunctbl[opcode] == op_illg_1) { opcode = 0x4AFC; } dp = table68k + opcode; @@ -1343,7 +1444,7 @@ static void m68k_verify (uaecptr addr, u } } -void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt) +void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt) { uaecptr newpc = 0; m68kpc_offset = addr - m68k_getpc (); @@ -1353,13 +1454,13 @@ void m68k_disasm (uaecptr addr, uaecptr uae_u32 opcode; struct mnemolookup *lookup; struct instr *dp; - printf ("%08lx: ", m68k_getpc () + m68kpc_offset); + fprintf (f, "%08lx: ", m68k_getpc () + m68kpc_offset); for (opwords = 0; opwords < 5; opwords++){ - printf ("%04x ", get_iword_1 (m68kpc_offset + opwords*2)); + fprintf (f, "%04x ", get_iword_1 (m68kpc_offset + opwords*2)); } opcode = get_iword_1 (m68kpc_offset); m68kpc_offset += 2; - if (cpufunctbl[cft_map (opcode)] == op_illg_1) { + if (cpufunctbl[opcode] == op_illg_1) { opcode = 0x4AFC; } dp = table68k + opcode; @@ -1371,69 +1472,161 @@ void m68k_disasm (uaecptr addr, uaecptr if (ccpt != 0) { strncpy (ccpt, ccnames[dp->cc], 2); } - printf ("%s", instrname); + fprintf (f, "%s", instrname); switch (dp->size){ - case sz_byte: printf (".B "); break; - case sz_word: printf (".W "); break; - case sz_long: printf (".L "); break; - default: printf (" "); break; + case sz_byte: fprintf (f, ".B "); break; + case sz_word: fprintf (f, ".W "); break; + case sz_long: fprintf (f, ".L "); break; + default: fprintf (f, " "); break; } if (dp->suse) { newpc = m68k_getpc () + m68kpc_offset; - newpc += ShowEA (dp->sreg, dp->smode, dp->size, 0); + newpc += ShowEA (f, dp->sreg, dp->smode, dp->size, 0); } if (dp->suse && dp->duse) - printf (","); + fprintf (f, ","); if (dp->duse) { newpc = m68k_getpc () + m68kpc_offset; - newpc += ShowEA (dp->dreg, dp->dmode, dp->size, 0); + newpc += ShowEA (f, dp->dreg, dp->dmode, dp->size, 0); } if (ccpt != 0) { if (cctrue(dp->cc)) - printf (" == %08lx (TRUE)", newpc); + fprintf (f, " == %08lx (TRUE)", newpc); else - printf (" == %08lx (FALSE)", newpc); + fprintf (f, " == %08lx (FALSE)", newpc); } else if ((opcode & 0xff00) == 0x6100) /* BSR */ - printf (" == %08lx", newpc); - printf ("\n"); + fprintf (f, " == %08lx", newpc); + fprintf (f, "\n"); } if (nextpc) *nextpc = m68k_getpc () + m68kpc_offset; } -void m68k_dumpstate (uaecptr *nextpc) +void m68k_dumpstate (FILE *f, uaecptr *nextpc) { int i; for (i = 0; i < 8; i++){ - printf ("D%d: %08lx ", i, m68k_dreg(regs, i)); - if ((i & 3) == 3) printf ("\n"); + fprintf (f, "D%d: %08lx ", i, m68k_dreg(regs, i)); + if ((i & 3) == 3) fprintf (f, "\n"); } for (i = 0; i < 8; i++){ - printf ("A%d: %08lx ", i, m68k_areg(regs, i)); - if ((i & 3) == 3) printf ("\n"); + fprintf (f, "A%d: %08lx ", i, m68k_areg(regs, i)); + if ((i & 3) == 3) fprintf (f, "\n"); } if (regs.s == 0) regs.usp = m68k_areg(regs, 7); if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7); if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7); - printf ("USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n", - regs.usp,regs.isp,regs.msp,regs.vbr); - printf ("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n", - regs.t1, regs.t0, regs.s, regs.m, - GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask); + fprintf (f, "USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n", + regs.usp,regs.isp,regs.msp,regs.vbr); + fprintf (f, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n", + regs.t1, regs.t0, regs.s, regs.m, + GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask); for (i = 0; i < 8; i++){ - printf ("FP%d: %g ", i, regs.fp[i]); - if ((i & 3) == 3) printf ("\n"); + fprintf (f, "FP%d: %g ", i, regs.fp[i]); + if ((i & 3) == 3) fprintf (f, "\n"); } - printf ("N=%d Z=%d I=%d NAN=%d\n", - (regs.fpsr & 0x8000000) != 0, - (regs.fpsr & 0x4000000) != 0, - (regs.fpsr & 0x2000000) != 0, - (regs.fpsr & 0x1000000) != 0); + fprintf (f, "N=%d Z=%d I=%d NAN=%d\n", + (regs.fpsr & 0x8000000) != 0, + (regs.fpsr & 0x4000000) != 0, + (regs.fpsr & 0x2000000) != 0, + (regs.fpsr & 0x1000000) != 0); if (currprefs.cpu_compatible) - printf ("prefetch %08lx\n", (unsigned long)do_get_mem_long(®s.prefetch)); + fprintf (f, "prefetch %08lx\n", (unsigned long)do_get_mem_long(®s.prefetch)); - m68k_disasm(m68k_getpc (), nextpc, 1); + m68k_disasm (f, m68k_getpc (), nextpc, 1); if (nextpc) - printf ("next PC: %08lx\n", *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; }