/* * Reset emulator */ static void do_reset_machine (int hardreset) { #ifdef SAVESTATE if (savestate_state == STATE_RESTORE) restore_state (savestate_fname); else if (savestate_state == STATE_REWIND) savestate_rewind (); #endif /* following three lines must not be reordered or * fastram state restore breaks */ reset_all_systems (); customreset (); m68k_reset (); if (hardreset) { memset (chipmemory, 0, allocated_chipmem); write_log ("chipmem cleared\n"); } #ifdef SAVESTATE /* We may have been restoring state, but we're done now. */ if (savestate_state == STATE_RESTORE || savestate_state == STATE_REWIND) { map_overlay (1); fill_prefetch_slow (®s); /* compatibility with old state saves */ } savestate_restore_finish (); #endif fill_prefetch_slow (®s); if (currprefs.produce_sound == 0) eventtab[ev_audio].active = 0; handle_active_events (); inputdevice_updateconfig (&currprefs); }
void REGPARAM2 call_calltrap (int func) { uae_u32 retval = 0; int has_retval = (trapmode[func] & TRAPFLAG_NO_RETVAL) == 0; int implicit_rts = (trapmode[func] & TRAPFLAG_DORET) != 0; if (trapstr[func] && *trapstr[func] != 0 && trace_traps) write_log ("TRAP: %s\n", trapstr[func]); /* For monitoring only? */ if (traps[func] == NULL) { m68k_setpc (trapoldfunc[func]); fill_prefetch_slow (); return; } if (func < max_trap) { #ifdef CAN_DO_STACK_MAGIC if (trapmode[func] & TRAPFLAG_EXTRA_STACK) { execute_fn_on_extra_stack(traps[func], has_retval); return; } #endif retval = (*traps[func])(); } else write_log ("illegal emulator trap\n"); if (has_retval) m68k_dreg (regs, 0) = retval; if (implicit_rts) { m68k_do_rts (); fill_prefetch_slow (); } }
/* * Handles the emulator's side of a 68k call (from an extended trap) */ static uae_u32 REGPARAM2 m68k_call_handler (struct regstruct *regs) { ExtendedTrapContext *context = current_context; uae_u32 sp = m68k_areg (regs, 7); /* Push address of trap context on 68k stack. This is * so the return trap can find this context. */ sp -= sizeof (void *); put_pointer (sp, context); /* Push addr to return handler trap on 68k stack. * When the called m68k function does an RTS, the CPU will pull this * address off the stack and so call the return handler. */ sp -= 4; put_long (sp, m68k_return_trapaddr); m68k_areg (regs, 7) = sp; /* Set PC to address of 68k function to call. */ m68k_setpc (regs, context->call68k_func_addr); fill_prefetch_slow (&context->regs); /* End critical section: allow other traps run. */ uae_sem_post (&trap_mutex); /* Restore interrupts. */ regs->intmask = context->saved_regs.intmask; /* Dummy return value. */ return 0; }
/* * Call m68k function from an extended trap handler * * This function is to be called from the trap context. */ static uae_u32 trap_Call68k (ExtendedTrapContext *context, uaecptr func_addr) { /* Enter critical section - only one trap at a time, please! */ uae_sem_wait (&trap_mutex); current_context = context; /* Don't allow an interrupt and thus potentially another * trap to be invoked while we hold the above mutex. * This is probably just being paranoid. */ context->regs.intmask = 7; /* Set up function call address. */ context->call68k_func_addr = func_addr; /* Set PC to address of 68k call trap, so that it will be * executed when emulator context resumes. */ m68k_setpc (&context->regs, m68k_call_trapaddr); fill_prefetch_slow (&context->regs); /* Switch to emulator context. */ uae_sem_post (&context->switch_to_emu_sem); /* Wait for 68k call return handler to switch back to us. */ uae_sem_wait (&context->switch_to_trap_sem); /* End critical section. */ uae_sem_post (&trap_mutex); /* Get return value from 68k function called. */ return context->call68k_retval; }
/* * This function is called by the 68k interpreter to handle an emulator trap. * * trap_num = number of trap to invoke * regs = current 68k state */ void REGPARAM2 m68k_handle_trap (unsigned int trap_num) { struct Trap *trap = &traps[trap_num]; uae_u32 retval = 0; int has_retval = (trap->flags & TRAPFLAG_NO_RETVAL) == 0; int implicit_rts = (trap->flags & TRAPFLAG_DORET) != 0; if (trap->name && trap->name[0] != 0 && trace_traps) write_log (L"TRAP: %s\n", trap->name); if (trap_num < trap_count) { if (trap->flags & TRAPFLAG_EXTRA_STACK) { /* Handle an extended trap. * Note: the return value of this trap is passed back to 68k * space via a separate, dedicated simple trap which the trap * handler causes to be invoked when it is done. */ trap_HandleExtendedTrap (trap->handler, has_retval); } else { /* Handle simple trap */ retval = (trap->handler) (NULL); if (has_retval) m68k_dreg (regs, 0) = retval; if (implicit_rts) { m68k_do_rts (); fill_prefetch_slow (); } } } else write_log (L"Illegal emulator trap\n"); }
static void do_stack_magic (TrapFunction f, struct extra_stack *s, int has_retval) { switch (setjmp (s->stackswap_env)) { case 0: /* Returning directly */ current_extra_stack = s; if (has_retval == -1) { /*write_log ("finishing m68k mode return\n");*/ longjmp (s->m68kcall_env, 1); } /*write_log ("calling native function\n");*/ transfer_control (s, EXTRA_STACK_SIZE, stack_stub, f, has_retval); /* not reached */ abort (); case 1: /*write_log ("native function complete\n");*/ /* Returning normally. */ if (stack_has_retval (s, EXTRA_STACK_SIZE)) m68k_dreg (regs, 0) = get_retval_from_stack (s, EXTRA_STACK_SIZE); free_extra_stack (s); break; case 2: { /* Returning to do a m68k call. We're now back on the main stack. */ uaecptr a7 = m68k_areg (regs, 7) -= (sizeof (void *) + 7) & ~3; /* Save stack to restore */ *((void **)get_real_address (a7 + 4)) = s; /* Save special return address: this address contains a * calltrap that will longjmp to the right stack. */ put_long (m68k_areg (regs, 7), RTAREA_BASE + 0xFF00); m68k_setpc (s->m68kcall_addr); fill_prefetch_slow (); /*write_log ("native function calls m68k\n");*/ break; } } current_extra_stack = 0; }
static void ersatz_init (void) { int f; uaecptr request; uaecptr a; already_failed = 0; write_log ("initializing kickstart replacement\n"); if (disk_empty (0)) { already_failed = 1; notify_user (NUMSG_KICKREP); uae_restart (-1, NULL); return; } regs.s = 0; /* Set some interrupt vectors */ for (a = 8; a < 0xC0; a += 4) { put_long (a, 0xF8001A); } regs.isp = regs.msp = regs.usp = 0x800; m68k_areg(®s, 7) = 0x80000; regs.intmask = 0; /* Build a dummy execbase */ put_long (4, m68k_areg(®s, 6) = 0x676); put_byte (0x676 + 0x129, 0); for (f = 1; f < 105; f++) { put_word (0x676 - 6*f, 0x4EF9); put_long (0x676 - 6*f + 2, 0xF8000C); } /* Some "supported" functions */ put_long (0x676 - 456 + 2, 0xF80014); put_long (0x676 - 216 + 2, 0xF80020); put_long (0x676 - 198 + 2, 0xF80026); put_long (0x676 - 204 + 2, 0xF8002c); put_long (0x676 - 210 + 2, 0xF8002a); /* Build an IORequest */ request = 0x800; put_word (request + 0x1C, 2); put_long (request + 0x28, 0x4000); put_long (request + 0x2C, 0); put_long (request + 0x24, 0x200 * 4); m68k_areg(®s, 1) = request; ersatz_doio (); /* kickstart disk loader */ if (get_long(0x4000) == 0x4b49434b) { /* a kickstart disk was found in drive 0! */ write_log ("Loading Kickstart rom image from Kickstart disk\n"); /* print some notes... */ write_log ("NOTE: if UAE crashes set CPU to 68000 and/or chipmem size to 512KB!\n"); /* read rom image from kickstart disk */ put_word (request + 0x1C, 2); put_long (request + 0x28, 0xF80000); put_long (request + 0x2C, 0x200); put_long (request + 0x24, 0x200 * 512); m68k_areg(®s, 1) = request; ersatz_doio (); /* read rom image once again to mirror address space. not elegant, but it works... */ put_word (request + 0x1C, 2); put_long (request + 0x28, 0xFC0000); put_long (request + 0x2C, 0x200); put_long (request + 0x24, 0x200 * 512); m68k_areg(®s, 1) = request; ersatz_doio (); disk_eject (0); m68k_setpc (®s, 0xFC0002); fill_prefetch_slow (®s); uae_reset (0); ersatzkickfile = 0; return; } m68k_setpc (®s, 0x400C); fill_prefetch_slow (®s); /* Init the hardware */ put_long (0x3000, 0xFFFFFFFEul); put_long (0xDFF080, 0x3000); put_word (0xDFF088, 0); put_word (0xDFF096, 0xE390); put_word (0xDFF09A, 0xE02C); put_word (0xDFF09E, 0x0000); put_word (0xDFF092, 0x0038); put_word (0xDFF094, 0x00D0); put_word (0xDFF08E, 0x2C81); put_word (0xDFF090, 0xF4C1); put_word (0xDFF02A, 0x8000); put_byte (0xBFD100, 0xF7); put_byte (0xBFEE01, 0); put_byte (0xBFEF01, 0x08); put_byte (0xBFDE00, 0x04); put_byte (0xBFDF00, 0x84); put_byte (0xBFDD00, 0x9F); put_byte (0xBFED01, 0x9F); }