示例#1
0
文件: fpp.c 项目: bernds/UAE
static void fpu_op_illg (uae_u32 opcode, int pcoffset)
{
    if ((currprefs.cpu_model == 68060 && (currprefs.fpu_model == 0 || (regs.pcr & 2)))
	|| (currprefs.cpu_model == 68040 && currprefs.fpu_model == 0)) {
	/* 68040 unimplemented/68060 FPU disabled exception.
	 * Line F exception with different stack frame.. */
	uaecptr newpc = m68k_getpc ();
	uaecptr oldpc = newpc - pcoffset;
	MakeSR ();
	if (!regs.s) {
	    regs.usp = m68k_areg (regs, 7);
	    m68k_areg (regs, 7) = regs.isp;
	}
	regs.s = 1;
	m68k_areg (regs, 7) -= 4;
	put_long (m68k_areg (regs, 7), oldpc);
	m68k_areg (regs, 7) -= 4;
	put_long (m68k_areg (regs, 7), oldpc);
	m68k_areg (regs, 7) -= 2;
	put_word (m68k_areg (regs, 7), 0x4000 + 11 * 4);
	m68k_areg (regs, 7) -= 4;
	put_long (m68k_areg (regs, 7), newpc);
	m68k_areg (regs, 7) -= 2;
	put_word (m68k_areg (regs, 7), regs.sr);
	write_log ("68040/060 FPU disabled exception PC=%x\n", newpc);
	newpc = get_long (regs.vbr + 11 * 4);
	m68k_setpc (newpc);
	return;
    }
    op_illg (opcode);
}
示例#2
0
/**
 * This is called after completion of each VDI call
 */
unsigned long OpCode_VDI(uae_u32 opcode)
{
	Uint32 pc = M68000_GetPC();

	/* this is valid only after VDI trap, called from cartridge code */
	if (VDI_OldPC && pc >= 0xfa0000 && pc < 0xfc0000)
	{
		VDI_Complete();

		/* Set PC back to where originated from to continue instruction decoding */
		m68k_setpc(VDI_OldPC);
		VDI_OldPC = 0;
	}
	else
	{
		/* illegal instruction */
		op_illg(opcode);
	}

	get_word_prefetch (0);
	regs.ir = regs.irc;
	get_word_prefetch(2);

	return 4 * CYCLE_UNIT / 2;
}
示例#3
0
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 ();
    }
}
示例#4
0
文件: traps.c 项目: ApolloniaUK/PUAE
/*
 * Call m68k function from an extended trap handler
 *
 * This function is to be called from the trap context.
 */
static uae_u32 trap_Call68k (TrapContext *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. */
	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 (m68k_call_trapaddr);
	fill_prefetch ();

	/* 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;
}
示例#5
0
文件: traps.c 项目: ApolloniaUK/PUAE
/*
 * Handles the emulator's side of a 68k call (from an extended trap)
 */
static uae_u32 REGPARAM3 m68k_call_handler (TrapContext *dummy_ctx)
{
	TrapContext *context = current_context;

	uae_u32 sp;

	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 (context->call68k_func_addr);
	fill_prefetch ();

	/* 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;
}
示例#6
0
void map_overlay (int chip)
{
    int i = allocated_chipmem > 0x200000 ? (allocated_chipmem >> 16) : 32;
    addrbank *cb;

    cb = &chipmem_bank;
    if (chip)
	map_banks (cb, 0, i, allocated_chipmem);
    else
	map_banks (&kickmem_bank, 0, i, 0x80000);
    if (savestate_state != STATE_RESTORE)
	m68k_setpc (m68k_getpc ());
}
示例#7
0
文件: ersatz.c 项目: Yamakuzure/PUAE
void ersatz_perform (uint16_t what)
{
	switch (what) {
	case EOP_INIT:
		ersatz_init ();
		break;

	case EOP_SERVEINT:
		{
			uint16_t intreq = get_word (0xDFF01E);
			/* Just reset all the interrupt request bits */
			if (intreq & 0x0008)
				get_byte (0xbfed01); /* possible keyboard interrupt */
			put_word (0xDFF09C, intreq & 0x3FFF);
			break;
		}

	case EOP_DOIO:
		ersatz_doio ();
		break;

	case EOP_AVAILMEM:
		m68k_dreg (regs, 0) = m68k_dreg (regs, 1) & 4 ? 0 : 0x70000;
		break;

	case EOP_ALLOCMEM:
		m68k_dreg (regs, 0) = m68k_dreg (regs, 1) & 4 ? 0 : 0x0F000;
		break;

	case EOP_ALLOCABS:
		m68k_dreg (regs, 0) = m68k_areg (regs, 1);
		break;

	case EOP_NIMP:
		write_log (_T("Unimplemented Kickstart function called\n"));
		ersatz_failed ();

		/* fall through */
	case EOP_LOOP:
		m68k_setpc (0xF80010);
		break;

	case EOP_OPENLIB:
	default:
		write_log (_T("Internal error. Giving up.\n"));
		ersatz_failed ();
	}
}
示例#8
0
void ersatz_perform (uae_u16 what)
{
    switch (what) {
     case EOP_INIT:
	ersatz_init ();
	break;

     case EOP_SERVEINT:
	/* Just reset all the interrupt request bits */
	put_word (0xDFF09C, get_word (0xDFF01E) & 0x3FFF);
	break;

     case EOP_DOIO:
	ersatz_doio ();
	break;

     case EOP_AVAILMEM:
	m68k_dreg (regs, 0) = m68k_dreg (regs, 1) & 4 ? 0 : 0x70000;
	break;

     case EOP_ALLOCMEM:
	m68k_dreg (regs, 0) = m68k_dreg (regs, 1) & 4 ? 0 : 0x0F000;
	break;

     case EOP_ALLOCABS:
	m68k_dreg (regs, 0) = m68k_areg (regs, 1);
	break;

     case EOP_NIMP:
	printf ("Unimplemented Kickstart function called\n");
	ersatz_failed ();
	break;

	/* fall through */
     case EOP_LOOP:
	m68k_setpc (0xF80010);
	break;

     case EOP_OPENLIB:
     default:
	printf ("Internal error. Giving up.\n");
	ersatz_failed ();
	break;
    }
}
示例#9
0
/*
 * Thread body for trap context
 */
static void *trap_thread (void *arg)
{
    ExtendedTrapContext *context = (ExtendedTrapContext *) arg;

    uae_set_thread_priority (2);

    /* Wait until main thread is ready to switch to the
     * this trap context. */
    uae_sem_wait (&context->switch_to_trap_sem);

    /* Execute trap handler function. */
    context->trap_retval = context->trap_handler ((TrapContext *)context);

    /* Trap handler is done - we still need to tidy up
     * and make sure the handler's return value is propagated
     * to the calling 68k thread.
     *
     * We do this by causing our exit handler to be executed on the 68k context.
     */

    /* Enter critical section - only one trap at a time, please! */
    uae_sem_wait (&trap_mutex);

    /* 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 PC to address of the exit handler, so that it will be called
     * when the 68k context resumes. */
    m68k_setpc (&context->regs, exit_trap_trapaddr);
    current_context = context;

    /* Switch back to 68k context */
    uae_sem_post (&context->switch_to_emu_sem);

    /* Good bye, cruel world... */

    /* dummy return value */
    write_log("trap_thread: exit (arg=0x%08X)\n", arg);
    return 0;
}
示例#10
0
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;
}
示例#11
0
void comp_fscc_opp (uae_u32 opcode, uae_u16 extra)
{
    uae_u32 ad;
    int cc;
    int reg;

    if (!currprefs.compfpu) {
		FAIL(1);
		return;
    }

#if DEBUG_FPP
    write_log (_T("JIT: fscc_opp at %08lx\n"), M68K_GETPC);
#endif

    if (extra & 0x20) {  /* only cc from 00 to 1f are defined */
		FAIL(1);
		return;
    }
	if ((opcode & 0x38) != 0) { /* We can only do to integer register */
		FAIL(1);
		return;
    }

    fflags_into_flags(S2);
    reg = (opcode & 7);

    mov_l_ri(S1,255);
    mov_l_ri(S4,0);
    switch (extra & 0x0f) { /* according to fpp.c, the 0x10 bit is ignored */
	case 0: break;  /* set never */
     case 1: mov_l_rr(S2,S4);
		cmov_l_rr(S4,S1,4);
	cmov_l_rr(S4,S2,10); break;
     case 2: cmov_l_rr(S4,S1,7); break;
     case 3: cmov_l_rr(S4,S1,3); break;
     case 4: mov_l_rr(S2,S4);
		cmov_l_rr(S4,S1,2);
	cmov_l_rr(S4,S2,10); break;
     case 5: mov_l_rr(S2,S4);
		cmov_l_rr(S4,S1,6);
	cmov_l_rr(S4,S2,10); break;
     case 6: cmov_l_rr(S4,S1,5); break;
     case 7: cmov_l_rr(S4,S1,11); break;
     case 8: cmov_l_rr(S4,S1,10); break;
     case 9: cmov_l_rr(S4,S1,4); break;
     case 10: cmov_l_rr(S4,S1,10); cmov_l_rr(S4,S1,7); break;
     case 11: cmov_l_rr(S4,S1,4); cmov_l_rr(S4,S1,3); break;
     case 12: cmov_l_rr(S4,S1,2); break;
     case 13: cmov_l_rr(S4,S1,6); break;
     case 14: cmov_l_rr(S4,S1,5); cmov_l_rr(S4,S1,10); break;
     case 15: mov_l_rr(S4,S1); break;
	}

    if (!(opcode & 0x38))
		mov_b_rr(reg,S4);
#if 0
    else {
	abort();
	if (!comp_fp_adr (opcode)) {
	    m68k_setpc (m68k_getpc () - 4);
	    op_illg (opcode, regs);
	}
	else
	    put_byte (ad, cc ? 0xff : 0x00);
    }
#endif
}
示例#12
0
文件: state.c 项目: debrouxl/tiemu
/*
  Must be done between init_hardware and M68000_run.
  Typically called after initLib68k.
  This function (re)load the state of the calculator.
  It automagically determine the state file format.

  Return an error code if an error occured, 0 otherwise
*/
int ti68k_state_load(char *filename)
{
	FILE *f;
  	IMG_INFO img;
  	SAV_INFO sav;
	Ti68kHardware thw;
    int ret;
	long pos;
	int i;
  
  	// No filename, exits
	if(!strcmp(filename, ""))
		return 0;
  
  	// Open file
  	printl(0, "loading state image: %s\n", g_basename(filename));
  	f = fopen(filename, "rb");
  	if(f == NULL)
  		return ERR_CANT_OPEN;
  	
  	// Compare image infos with current image
	fread(&img, 1, sizeof(IMG_INFO), f);
	if(memcmp(&img, &img_infos, sizeof(IMG_INFO) - sizeof(char *)))
		return ERR_INVALID_STATE;

    // Determine state image revision for backwards compatibility
	pos = ftell(f);
	fread(&sav.revision, sizeof(sav.revision), 1, f);
	fread(&sav.size, sizeof(sav.revision), 1, f);
	fseek(f, pos, SEEK_SET);

	if(sav.revision != SAV_REVISION)
		return ERR_INVALID_STATE;

	// Load state image infos
    fread(&sav, 1, sizeof(SAV_INFO), f);
	
	// Load internal hardware (registers and special flags)
    ret = fseek(f, sav.regs_offset, SEEK_SET);
    fread(&regs, sizeof(regs), 1, f);
    
    // Load I/O ports state
    ret = fseek(f, sav.io_offset, SEEK_SET);
    fread(tihw.io , tihw.io_size, 1, f);
    fread(tihw.io2, tihw.io_size, 1, f);
    
    // Load RAM content
    ret = fseek(f, sav.ram_offset, SEEK_SET);
    fread(tihw.ram, tihw.ram_size, 1, f);

	// Load extra infos
	ret = fseek(f, sav.misc_offset, SEEK_SET);
	fread(&thw, sizeof(Ti68kHardware), 1, f);
	tihw.on_off = thw.on_off;
	tihw.lcd_adr = thw.lcd_adr;
	tihw.contrast = thw.contrast;
	tihw.protect = thw.protect;
	tihw.archive_limit = thw.archive_limit;
	memcpy(tihw.ram_exec, thw.ram_exec, 32);

	// Load modified FLASH segments
	ret = fseek(f, sav.rom_offset, SEEK_SET);
	for(i=0; i<wsm.nblocks; i++)
    {
		fread(&wsm.changed[i], sizeof(int), 1, f);
		if(wsm.changed[i])
			fread(&tihw.rom[i<<16], 1, 65536, f);
    }

    // Load bkpts
    ti68k_bkpt_clear_access();
	ti68k_bkpt_clear_range();
    ti68k_bkpt_clear_address();
	ti68k_bkpt_clear_exception();
	ti68k_bkpt_clear_pgmentry();

    ret = fseek(f, sav.bkpts_offset, SEEK_SET);
    load_bkpt(f, &bkpts.code);
    load_bkpt(f, &bkpts.exception);
	load_bkpt(f, &bkpts.pgmentry);

    load_bkpt(f, &bkpts.mem_rb);
	load_bkpt(f, &bkpts.mem_rw);
	load_bkpt(f, &bkpts.mem_rl);
	load_bkpt(f, &bkpts.mem_wb);
	load_bkpt(f, &bkpts.mem_ww);
	load_bkpt(f, &bkpts.mem_wl);

    load_bkpt2(f, &bkpts.mem_rng_r);
	load_bkpt2(f, &bkpts.mem_rng_w);
    
	// Update UAE structures
	m68k_setpc(m68k_getpc());
    MakeFromSR();

    fclose(f); 
  
  	return 0;
}
示例#13
0
void ATrap::DoCall (uint16 trapWord)
{
	// Stop all profiling activities. Stop cycle counting and stop the
	// recording of function entries and exits.  We want our calls to
	// ROM functions to be as transparent as possible.

	StDisableAllProfiling	stopper;


	// Assert that the function we're trying to call is implemented.
	//
	// Oops...bad test...this doesn't work when we're calling a library.
	// Instead, since we now invoke ROM functions by creating a TRAP $F
	// sequence, we'll let our TRAP $F handler deal with validating the
	// function call (it does that anyway).

//	EmAssert (LowMem::GetTrapAddress (trapWord));

	// We call the ROM function by dummying up a sequence of 68xxx instructions
	// for it.  The sequence of instructions is:
	//
	//			TRAP	$F
	//			DC.W	<dispatch number>
	//			TRAP	$C
	//
	// The first two words invoke the function (calling any head- or tailpatches
	// along the way).  The third word allows the emulator to regain control
	// after the function has returned.
	//
	// Note: this gets a little ugly on little-endian machines.  The following
	// instructions are stored on the emulator's stack.  This memory is mapped
	// into the emulated address space in such a fashion that no byteswapping of
	// word or long values occurs.  Thus, we have to put the data into Big Endian
	// format when putting it into the array.
	//
	// However, opcodes are a special case.  They are optimized in the emulator
	// for fast access.  Opcodes are *always* fetched a word at a time in host-
	// endian order.  Thus, the opcodes below have to be stored in host-endian
	// order.  That's why there's no call to Canonical to put them into Big
	// Endian order.

	uint16	code[] = { kOpcode_ROMCall, trapWord, kOpcode_ATrapReturn };

	// Oh, OK, we do have to byteswap the trapWord.  Opcodes are fetched with
	// EmMemDoGet16, which always gets the value in host byte order.  The
	// trapWord is fetched with EmMemGet16, which gets values according to the
	// rules of the memory bank.  For the dummy bank, the defined byte order
	// is Big Endian.

	Canonical (code[1]);

	// Map in the code stub so that the emulation code can access it.

	StMemoryMapper	mapper (code, sizeof (code));

	// Prepare to handle the TRAP 12 exception.

	EmAssert (gCPU68K);
	gCPU68K->InstallHookException (kException_ATrapReturn, PrvHandleTrap12);

	// Point the PC to our code.

	emuptr	newPC = EmBankMapped::GetEmulatedAddress (code);
	m68k_setpc (newPC);

	// Execute until the next break.

	try
	{
		EmAssert (gSession);
		gSession->ExecuteSubroutine ();
	}
	catch (EmExceptionReset& e)
	{
		e.SetTrapWord (trapWord);

		// Remove the TRAP 12 exception handler.

		EmAssert (gCPU68K);
		gCPU68K->RemoveHookException (kException_ATrapReturn, PrvHandleTrap12);

		throw;
	}

	// Remove the TRAP 12 exception handler.

	EmAssert (gCPU68K);
	gCPU68K->RemoveHookException (kException_ATrapReturn, PrvHandleTrap12);
}
示例#14
0
// Service an interrupt request and start exception processing
void m68ki_exception_interrupt(uint32_t intLevel)
{
#if 0
	uint vector;
	uint sr;
	uint new_pc;

	/* Turn off the stopped state */
	CPU_STOPPED &= ~STOP_LEVEL_STOP;

	/* If we are halted, don't do anything */
	if(CPU_STOPPED)
		return;

	/* Acknowledge the interrupt */
	vector = m68ki_int_ack(int_level);

	/* Get the interrupt vector */
	if(vector == M68K_INT_ACK_AUTOVECTOR)
		/* Use the autovectors.  This is the most commonly used implementation */
		vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level;
	else if(vector == M68K_INT_ACK_SPURIOUS)
		/* Called if no devices respond to the interrupt acknowledge */
		vector = EXCEPTION_SPURIOUS_INTERRUPT;
	else if(vector > 255)
	{
		M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n",
			 m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector));
		return;
	}

	/* Start exception processing */
	sr = m68ki_init_exception();

	/* Set the interrupt mask to the level of the one being serviced */
	FLAG_INT_MASK = int_level<<8;

	/* Get the new PC */
	new_pc = m68ki_read_data_32((vector<<2) + REG_VBR);

	/* If vector is uninitialized, call the uninitialized interrupt vector */
	if(new_pc == 0)
		new_pc = m68ki_read_data_32((EXCEPTION_UNINITIALIZED_INTERRUPT<<2) + REG_VBR);

	/* Generate a stack frame */
	m68ki_stack_frame_0000(REG_PC, sr, vector);

	if(FLAG_M && CPU_TYPE_IS_EC020_PLUS(CPU_TYPE))
	{
		/* Create throwaway frame */
		m68ki_set_sm_flag(FLAG_S);	/* clear M */
		sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */
		m68ki_stack_frame_0001(REG_PC, sr, vector);
	}

	m68ki_jump(new_pc);

	/* Defer cycle counting until later */
	CPU_INT_CYCLES += CYC_EXCEPTION[vector];

#if !M68K_EMULATE_INT_ACK
	/* Automatically clear IRQ if we are not using an acknowledge scheme */
	CPU_INT_LEVEL = 0;
#endif /* M68K_EMULATE_INT_ACK */
#else
	// Turn off the stopped state (N.B.: normal 68K behavior!)
	regs.stopped = 0;

//JLH: need to add halt state?
// prolly, for debugging/alpine mode... :-/
// but then again, this should be handled already by the main execution loop :-P
	// If we are halted, don't do anything
//	if (regs.stopped)
//		return;

	// Acknowledge the interrupt (NOTE: This is a user supplied function!)
	uint32_t vector = irq_ack_handler(intLevel);

	// Get the interrupt vector
	if (vector == M68K_INT_ACK_AUTOVECTOR)
		// Use the autovectors.  This is the most commonly used implementation
		vector = EXCEPTION_INTERRUPT_AUTOVECTOR + intLevel;
	else if (vector == M68K_INT_ACK_SPURIOUS)
		// Called if no devices respond to the interrupt acknowledge
		vector = EXCEPTION_SPURIOUS_INTERRUPT;
	else if (vector > 255)
	{
//		M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n",
//			 m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector));
		return;
	}

	// Start exception processing
	uint32_t sr = m68ki_init_exception();

	// Set the interrupt mask to the level of the one being serviced
	regs.intmask = intLevel;

#if 0
extern int startM68KTracing;
if (startM68KTracing)
{
	printf("IRQ: old PC=%06X, ", regs.pc);
}
#endif

	// Get the new PC
	uint32_t newPC = m68k_read_memory_32(vector << 2);

#if 0
if (startM68KTracing)
{
	printf("new PC=%06X, vector=%u, ", newPC, vector);
}
#endif

	// If vector is uninitialized, call the uninitialized interrupt vector
	if (newPC == 0)
		newPC = m68k_read_memory_32(EXCEPTION_UNINITIALIZED_INTERRUPT << 2);

	// Generate a stack frame
	m68ki_stack_frame_3word(regs.pc, sr);

	m68k_setpc(newPC);
#if 0
if (startM68KTracing)
{
	printf("(PC=%06X)\n", regs.pc);
}
#endif

	// Defer cycle counting until later
	regs.interruptCycles += 56;	// NOT ACCURATE-- !!! FIX !!!
//	CPU_INT_CYCLES += CYC_EXCEPTION[vector];
#endif
}
示例#15
0
文件: state.c 项目: debrouxl/tiemu
/*
  	This function saves the state of the calculator.
  	Can be called at any time.

  	Return an error code if an error occured, 0 otherwise
*/
int ti68k_state_save(char *filename)
{
  	FILE *f;
  	IMG_INFO *img = &img_infos;
    SAV_INFO sav;
	int i;
  
  	if(!strlen(filename))
  		return ERR_CANT_OPEN;
  
  	// Open file
  	printl(0, "Saving state image (TiEmu v2.00 format): %s\n", filename);
  	f = fopen(filename, "wb");
  	if(f == NULL)
  		return ERR_CANT_OPEN;
  	
  	// Save current image infos
	fwrite(img, 1, sizeof(IMG_INFO), f);

    // Fill state image infos
	sav.revision = SAV_REVISION;
	sav.size = sizeof(SAV_INFO);

    sav.regs_offset = sizeof(IMG_INFO) + sizeof(SAV_INFO);
    sav.io_offset = sav.regs_offset + sizeof(regs);
    sav.ram_offset = sav.io_offset + 2*tihw.io_size;
	sav.misc_offset = sav.ram_offset + tihw.ram_size;
#if 1
	sav.rom_offset = sav.misc_offset + sizeof(Ti68kHardware);
    sav.bkpts_offset = sav.rom_offset + wsm.nblocks*sizeof(int) + hw_flash_nblocks()*65536;
#else
	sav.bkpts_offset = sav.misc_offset + sizeof(Ti68kHardware);
#endif

    fwrite(&sav, 1, sizeof(SAV_INFO), f);
	
	// Update UAE structures
    MakeSR();
    m68k_setpc(m68k_getpc());
    
    // Save registers and special flags
    fwrite(&regs, sizeof(regs), 1, f);
    
    // Save I/O ports state
    fwrite(tihw.io , tihw.io_size, 1, f);
    fwrite(tihw.io2, tihw.io_size, 1, f);
    
    // Save RAM content
    fwrite(tihw.ram, tihw.ram_size, 1, f);

	// Save misc informations
	fwrite(&tihw, sizeof(Ti68kHardware), 1, f);

	// Save modified FLASH segments
	for(i=0; i<wsm.nblocks; i++)
    {
		fwrite(&wsm.changed[i], sizeof(int), 1, f);
		if(wsm.changed[i])
			fwrite(&tihw.rom[i<<16], 1, 65536, f);
    }

    // Save breakpoints (address, access, range, exception)
    save_bkpt(f, bkpts.code);
    save_bkpt(f, bkpts.exception);
	save_bkpt(f, bkpts.pgmentry);

    save_bkpt(f, bkpts.mem_rb);
	save_bkpt(f, bkpts.mem_rw);
	save_bkpt(f, bkpts.mem_rl);
	save_bkpt(f, bkpts.mem_wb);
	save_bkpt(f, bkpts.mem_ww);
	save_bkpt(f, bkpts.mem_wl);

    save_bkpt2(f, bkpts.mem_rng_r);
	save_bkpt2(f, bkpts.mem_rng_w);
    
    fclose(f);

  	return 0;
}
示例#16
0
/*
  Must be done between init_hardware and M68000_run.
  Typically called after initLib68k.
  This function (re)load the state of the calculator.
  It automagically determine the state file format.

  Return an error code if an error occured, 0 otherwise
*/
int ti68k_state_load(const char *filename)
{
	FILE *f;
  	IMG_INFO img;
  	SAV_INFO sav;
	Ti68kHardware thw;
    int ret;
	long pos;
	int i;
	gchar *rf=NULL, *tf=NULL;
  
  	// No filename, exits
	if(!strcmp(filename, ""))
		return 0;
  
  	// Open file
  	tiemu_info(_("loading state image: %s"), g_basename(filename));
  	f = fopen(filename, "rb");
  	if(f == NULL)
  		return ERR_CANT_OPEN_STATE;
  	
  	// Load ROM image header
	fread(&img, 1, sizeof(IMG_INFO), f);

    // Determine state image revision and load state image header
	pos = ftell(f);
	fread(&sav.revision, sizeof(sav.revision), 1, f);
	fread(&sav.size, sizeof(sav.revision), 1, f);
	fseek(f, pos, SEEK_SET);
	fread(&sav, 1, sav.size, f);

	if(sav.revision < SAV_MINI)
	{
		fclose(f);
		return ERR_REVISION_MATCH;
	}

	// Does not accept state image different of emulator image
	if(ti68k_state_parse(filename, &rf, &tf) < 0)
	{
		if (rf) g_free(rf);
		if (tf) g_free(tf);
		return ERR_STATE_MATCH;
	}
	if (rf) g_free(rf);
	if (tf) g_free(tf);

	// Compare image infos with current image
	if(memcmp(&img, &img_infos, sizeof(IMG_INFO) - sizeof(char *)))
		return ERR_HEADER_MATCH;
	
	// Load internal hardware (registers and special flags)
    ret = fseek(f, sav.regs_offset, SEEK_SET);
    fread(&regs, sizeof(regs), 1, f);
    
    // Load I/O ports state
    ret = fseek(f, sav.io_offset, SEEK_SET);
    fread(tihw.io , tihw.io_size, 1, f);
    fread(tihw.io2, tihw.io2_size, 1, f);
	fread(tihw.io3, tihw.io3_size, 1, f);
    
    // Load RAM content
    ret = fseek(f, sav.ram_offset, SEEK_SET);
    fread(tihw.ram, tihw.ram_size, 1, f);

	// Load extra infos
	ret = fseek(f, sav.misc_offset, SEEK_SET);
	fread(&thw, sizeof(Ti68kHardware), 1, f);
	tihw.on_off = thw.on_off;
	tihw.lcd_adr = thw.lcd_adr;
	tihw.contrast = thw.contrast;
	tihw.protect = thw.protect;
	tihw.archive_limit = thw.archive_limit;
	memcpy(tihw.ram_exec, thw.ram_exec, sizeof(tihw.ram_exec));

	tihw.rtc3_beg = thw.rtc3_beg;
	tihw.rtc3_load = thw.rtc3_load;
	rtc3_state_load();

	// Load modified FLASH segments
	ret = fseek(f, sav.rom_offset, SEEK_SET);
	for(i=0; i<wsm.nblocks; i++)
    {
		fread(&wsm.changed[i], sizeof(int), 1, f);
		if(wsm.changed[i])
			fread(&tihw.rom[i<<16], 1, 65536, f);
    }

    // Load bkpts
    ti68k_bkpt_clear_access();
	ti68k_bkpt_clear_range();
    ti68k_bkpt_clear_address();
	ti68k_bkpt_clear_exception();
	ti68k_bkpt_clear_pgmentry();

    ret = fseek(f, sav.bkpts_offset, SEEK_SET);
    load_bkpt(f, &bkpts.code);
    load_bkpt(f, &bkpts.exception);
	load_bkpt(f, &bkpts.pgmentry);

    load_bkpt(f, &bkpts.mem_rb);
	load_bkpt(f, &bkpts.mem_rw);
	load_bkpt(f, &bkpts.mem_rl);
	load_bkpt(f, &bkpts.mem_wb);
	load_bkpt(f, &bkpts.mem_ww);
	load_bkpt(f, &bkpts.mem_wl);

    load_bkpt2(f, &bkpts.mem_rng_r);
	load_bkpt2(f, &bkpts.mem_rng_w);

	if(sav.revision >= 21)
		load_bkpt3(f, &bkpts.bits);
    
	// Update UAE structures
	m68k_setpc(m68k_getpc());
    MakeFromSR();

	fclose(f);

	// Update SAV file to latest revision
	if(sav.revision < SAV_REVISION)
	{
		ti68k_state_save(filename);
	}

  	return 0;
}
示例#17
0
// Pulse the RESET line on the CPU
void m68k_pulse_reset(void)
{
	static uint32_t emulation_initialized = 0;

	// The first call to this function initializes the opcode handler jump table
	if (!emulation_initialized)
	{
#if 0
		m68ki_build_opcode_table();
		m68k_set_int_ack_callback(NULL);
		m68k_set_bkpt_ack_callback(NULL);
		m68k_set_reset_instr_callback(NULL);
		m68k_set_pc_changed_callback(NULL);
		m68k_set_fc_callback(NULL);
		m68k_set_instr_hook_callback(NULL);
#else
		// Build opcode handler table here...
		read_table68k();
		do_merges();
		BuildCPUFunctionTable();
#endif
		emulation_initialized = 1;
	}

//	if (CPU_TYPE == 0)	/* KW 990319 */
//		m68k_set_cpu_type(M68K_CPU_TYPE_68000);

#if 0
	/* Clear all stop levels and eat up all remaining cycles */
	CPU_STOPPED = 0;
	SET_CYCLES(0);

	/* Turn off tracing */
	FLAG_T1 = FLAG_T0 = 0;
	m68ki_clear_trace();
	/* Interrupt mask to level 7 */
	FLAG_INT_MASK = 0x0700;
	/* Reset VBR */
	REG_VBR = 0;
	/* Go to supervisor mode */
	m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);

	/* Invalidate the prefetch queue */
#if M68K_EMULATE_PREFETCH
	/* Set to arbitrary number since our first fetch is from 0 */
	CPU_PREF_ADDR = 0x1000;
#endif /* M68K_EMULATE_PREFETCH */

	/* Read the initial stack pointer and program counter */
	m68ki_jump(0);
	REG_SP = m68ki_read_imm_32();
	REG_PC = m68ki_read_imm_32();
	m68ki_jump(REG_PC);
#else
	regs.spcflags = 0;
	regs.stopped = 0;
	regs.remainingCycles = 0;
	
	regs.intmask = 0x07;
	regs.s = 1;								// Supervisor mode ON

	// Read initial SP and PC
	m68k_areg(regs, 7) = m68k_read_memory_32(0);
	m68k_setpc(m68k_read_memory_32(4));
	refill_prefetch(m68k_getpc(), 0);
#endif
}
示例#18
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(&regs, 7) = 0x80000;
    regs.intmask = 0;

    /* Build a dummy execbase */
    put_long (4, m68k_areg(&regs, 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(&regs, 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(&regs, 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(&regs, 1) = request;
	ersatz_doio ();

	disk_eject (0);

	m68k_setpc (&regs, 0xFC0002);
	fill_prefetch_slow (&regs);
	uae_reset (0);
	ersatzkickfile = 0;
	return;
    }

    m68k_setpc (&regs, 0x400C);
    fill_prefetch_slow (&regs);

    /* 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);
}
示例#19
0
文件: uade.c 项目: Kinglions/modizer
/* this is called for each played song from newcpu.c/m68k_reset() */
void uade_reset(void)
{
  /* don't load anything under 0x1000 (execbase top at $1000) */
  const int modnameaddr = 0x00400;
  const int scoreaddr   = 0x01000;
  const int userstack   = 0x08500;
  const int superstack  = 0x08f00;
  const int playeraddr  = 0x09000;
  int relocaddr;
  int modaddr;
  int len;
  FILE *file;
  int bytesread;

  uint8_t command[UADE_MAX_MESSAGE_SIZE];
  struct uade_msg *um = (struct uade_msg *) command;

  int ret;

 nextsong:

  /* IMPORTANT:
     It seems that certain players don't work totally reliably if memory
     contains trash from previous songs. To be certain that each song is
     played from the same initial state of emulator we clear the memory
     from 0x400 to 'uade_highmem' each time a new song is played */
  uade_highmem = 0;
  while (uade_highmem < 0x800000) {
    if (!valid_address(0, uade_highmem + 0x10000))
      break;
    uade_highmem += 0x10000;
  }
  if (uade_highmem < 0x80000) {
    fprintf(stderr, "uadecore: There must be at least 512 KiB of amiga memory (%d bytes found).\n", uade_highmem);
    exit(-1);
  }
  if (uade_highmem < 0x200000) {
    fprintf(stderr, "uadecore: Warning: highmem == 0x%x (< 0x200000)!\n", uade_highmem);
  }
  memset(get_real_address(0), 0, uade_highmem);

  song.cur_subsong = song.min_subsong = song.max_subsong = 0;

  ret = uade_receive_string(song.scorename, UADE_COMMAND_SCORE, sizeof(song.scorename), &uadeipc);
  if (ret == 0) {
    fprintf(stderr, "uadecore: No more songs to play.\n");
    exit(0);
  } else if (ret < 0) {
    fprintf(stderr, "uadecore: Invalid input. Expected score name.\n");
    exit(-1);
  }
//	printf("got scorename %s\n",song.scorename);

  ret = uade_receive_string(song.playername, UADE_COMMAND_PLAYER, sizeof(song.playername), &uadeipc);
  if (ret == 0) {
    printf("uadecore: Expected player name. Got nothing.\n");
    exit(-1);
  } else if (ret < 0) {
    printf( "uadecore: Invalid input. Expected player name.\n");
    exit(-1);
  }
//	printf("got playername %s\n",song.playername);

  if (uade_dirname(uade_player_dir, song.playername, sizeof(uade_player_dir)) == NULL) {
    printf( "uadecore: Invalid dirname with player: %s\n", song.playername);
    exit(-1);
  }

  ret = uade_receive_message(um, sizeof command, &uadeipc);
  if (ret == 0) {
    printf("uadecore: Expected module name. Got nothing.\n");
    exit(-1);
  } else if (ret < 0) {
    printf( "uadecore: Invalid input. Expected module name.\n");
    exit(-1);
  }
  assert(um->msgtype == UADE_COMMAND_MODULE);
  if (um->size == 0) {
    song.modulename[0] = 0;
  } else {
    assert(um->size == (strlen((char *) um->data) + 1));
    strlcpy(song.modulename, (char *) um->data, sizeof(song.modulename));
  }
//	printf("got modulename %s\n",song.modulename);

  uade_set_automatic_song_end(1);

  uade_put_long(SCORE_EXEC_DEBUG, uade_execdebugboolean ? 0x12345678 : 0);
  uade_put_long(SCORE_VOLUME_TEST, voltestboolean);
  uade_put_long(SCORE_DMA_WAIT, uade_dmawait);
  uade_put_long(SCORE_MODULECHANGE, disable_modulechange);

  bytesread = uade_safe_load_name(playeraddr, song.playername, "player", uade_highmem - playeraddr);

  if (bytesread > (uade_highmem - playeraddr)) {
    fprintf (stderr, "uadecore: Player %s too big a file (%d bytes).\n", song.playername, bytesread);
    goto skiptonextsong;
  }
  if (bytesread == 0) {
    goto skiptonextsong;
  }

  /* fprintf(stderr, "uadecore: player '%s' (%d bytes)\n", song.playername, bytesread); */

  /* set player executable address for relocator */
  uade_put_long(SCORE_PLAYER_ADDR, playeraddr);
  len = uade_calc_reloc_size((uae_u32 *) get_real_address(playeraddr),
			     (uae_u32 *) get_real_address(playeraddr + bytesread));
  if (!len) {
    fprintf(stderr, "uadecore: Problem with reloc calculation.\n");
    goto skiptonextsong;
  }
  relocaddr  = ((playeraddr + bytesread) & 0x7FFFF000) + 0x4000;
  /* + 0x4000 for hippel coso (wasseremu) */
  modaddr = ((relocaddr + len) & 0x7FFFF000) + 0x2000;

  if (modaddr <= relocaddr) {
    /* this is very bad because sound core memory allocation will fail */
    fprintf(stderr, "uadecore: Warning: modaddr <= relocaddr: 0x%x <= 0x%x\n", modaddr, relocaddr);
  }

  uade_put_long(SCORE_RELOC_ADDR, relocaddr);  /*address for relocated player*/
  uade_put_long(SCORE_MODULE_ADDR, modaddr);   /* set module address */
  uade_put_long(SCORE_MODULE_LEN, 0);          /* set module size to zero */
  uade_put_long(SCORE_MODULE_NAME_ADDR, 0);    /* mod name address pointer */

  /* load the module if available */
  if (song.modulename[0]) {
    bytesread = uade_safe_load_name(modaddr, song.modulename, "module", uade_highmem - modaddr);
    if (bytesread > (uade_highmem - playeraddr)) {
      fprintf (stderr, "uadecore: Module %s too big a file (%d bytes).\n", song.modulename, bytesread);
      goto skiptonextsong;
    }
    if (bytesread == 0) {
      goto skiptonextsong;
    }

    uade_put_long(SCORE_MODULE_LEN, bytesread);

    if (!valid_address(modnameaddr, strlen(song.modulename) + 1)) {
      fprintf(stderr, "uadecore: Invalid address for modulename.\n");
      goto skiptonextsong;
    }

    strlcpy((char *) get_real_address(modnameaddr), song.modulename, 1024);
    uade_put_long(SCORE_MODULE_NAME_ADDR, modnameaddr);

  } else {

    if (!valid_address(modnameaddr, strlen(song.playername) + 1)) {
      fprintf(stderr, "uadecore: Invalid address for playername.\n");
      goto skiptonextsong;
    }

    strlcpy((char *) get_real_address(modnameaddr), song.playername, 1024);
    uade_put_long(SCORE_MODULE_NAME_ADDR, modnameaddr);

    bytesread = 0;
  }

  /* load sound core (score) */
  if ((file = fopen(song.scorename, "rb"))) {
    bytesread = uade_safe_load(scoreaddr, file, uade_highmem - scoreaddr);
    fclose(file);
  } else {
    fprintf (stderr, "uadecore: Can not load score (%s).\n", song.scorename);
    goto skiptonextsong;
  }

  m68k_areg(regs,7) = scoreaddr;
  m68k_setpc(scoreaddr);

  /* obey player format checking */
  uade_put_long(SCORE_FORCE, 0);
  /* set default subsong */
  uade_put_long(SCORE_SET_SUBSONG, 0);
  uade_put_long(SCORE_SUBSONG, 0);
  /* set PAL mode */
  uade_set_ntsc(0);

  /* pause bits (don't care!), for debugging purposes only */
  uade_put_long(SCORE_PREPAUSE, 0);
  uade_put_long(SCORE_POSTPAUSE, 0);
  /* set user and supervisor stack pointers */
  uade_put_long(SCORE_USER_STACK, userstack);
  uade_put_long(SCORE_SUPER_STACK, superstack);
  /* no message for score */
  uade_put_long(SCORE_OUTPUT_MSG, 0);
  if ((userstack - (scoreaddr + bytesread)) < 0x1000)
    fprintf(stderr, "uadecore: Amiga stack overrun warning.\n");

  flush_sound();

  /* note that uade_speed_hack can be negative (meaning that uade never uses
     speed hack, even if it's requested by the amiga player)! */
  uade_time_critical = 0;
  if (uade_speed_hack > 0) {
    uade_time_critical = 1;
  }

  uade_reboot = 0;

  uade_audio_output = 0;
  uade_audio_skip = 0;

  old_ledstate = gui_ledstate;

  if (uade_receive_short_message(UADE_COMMAND_TOKEN, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not receive token in uade_reset().\n");
    exit(-1);
  }

  if (uade_send_short_message(UADE_REPLY_CAN_PLAY, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not send 'CAN_PLAY' reply.\n");
    exit(-1);
  }
  if (uade_send_short_message(UADE_COMMAND_TOKEN, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not send token from uade_reset().\n");
    exit(-1);
  }

  set_sound_freq(UADE_DEFAULT_FREQUENCY);
  epoptionsize = 0;

  return;

 skiptonextsong:
  fprintf(stderr, "uadecore: Can not play. Reboot.\n");

  if (uade_receive_short_message(UADE_COMMAND_TOKEN, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not receive token in uade_reset().\n");
    exit(-1);
  }

  if (uade_send_short_message(UADE_REPLY_CANT_PLAY, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not send 'CANT_PLAY' reply.\n");
    exit(-1);
  }
  if (uade_send_short_message(UADE_COMMAND_TOKEN, &uadeipc)) {
    fprintf(stderr, "uadecore: Can not send token from uade_reset().\n");
    exit(-1);
  }
  goto nextsong;
}
示例#20
0
void comp_fpp_opp (uae_u32 opcode, uae_u16 extra)
{
    int reg;
    int sreg, prec = 0;
    int	dreg = (extra >> 7) & 7;
    int source = (extra >> 13) & 7;
    int	opmode = extra & 0x7f;

    if (!currprefs.compfpu) {
		FAIL(1);
		return;
    }
    switch (source) {
	case 3: /* FMOVE FPx, <EA> */
		if (comp_fp_put(opcode,extra) < 0)
	    FAIL(1);
		return;
	case 4: /* FMOVE.L  <EA>, ControlReg */
		if (!(opcode & 0x30)) { /* Dn or An */
			if (extra & 0x1000) { /* FPCR */
		    	mov_l_mr((uae_u32)&regs.fpcr,opcode & 15);
#if USE_X86_FPUCW
		    	mov_l_rr(S1,opcode & 15);
		    	and_l_ri(S1,0xf0);
		    	fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
#endif
				return;
			}
			if (extra & 0x0800) { /* FPSR */
				FAIL(1);
				return;
				// set_fpsr(m68k_dreg (regs, opcode & 15));
			}
			if (extra & 0x0400) { /* FPIAR */
				mov_l_mr((uae_u32)&regs.fpiar,opcode & 15); return;
			}
	}
	else if ((opcode & 0x3f) == 0x3c) {
			if (extra & 0x1000) { /* FPCR */
		    	uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4);
		    	mov_l_mi((uae_u32)&regs.fpcr,val);
#if USE_X86_FPUCW
		    	mov_l_ri(S1,val&0xf0);
		    	fldcw_m_indexed(S1,(uae_u32)x86_fpucw);
#endif
				return;
			}
			if (extra & 0x0800) { /* FPSR */
			    FAIL(1);
			    return;
			}
			if (extra & 0x0400) { /* FPIAR */
				uae_u32 val=comp_get_ilong((m68k_pc_offset+=4)-4);
				mov_l_mi((uae_u32)&regs.fpiar,val);
				return;
			}
		}
		FAIL(1);
		return;
	case 5: /* FMOVE.L  ControlReg, <EA> */
		if (!(opcode & 0x30)) { /* Dn or An */
			if (extra & 0x1000) { /* FPCR */
				mov_l_rm(opcode & 15,(uae_u32)&regs.fpcr); return;
			}
			if (extra & 0x0800) { /* FPSR */
				FAIL(1);
				return;
			}
			if (extra & 0x0400) { /* FPIAR */
				mov_l_rm(opcode & 15,(uae_u32)&regs.fpiar); return;
			}
		}
		FAIL(1);
		return;
	case 6:
	case 7:
		{
	    uae_u32 list = 0;
	    int incr = 0;
	    if (extra & 0x2000) {
			uae_u32 ad;

			/* FMOVEM FPP->memory */
			switch ((extra >> 11) & 3) { /* Get out early if failure */
			case 0:
			case 2:
				break;
			case 1:
			case 3:
			default:
		    FAIL(1); return;
		}
		ad = comp_fp_adr (opcode);
		if (ad < 0) {
		    m68k_setpc (m68k_getpc () - 4);
		    op_illg (opcode);
		    return;
		}
		switch ((extra >> 11) & 3) {
		case 0:	/* static pred */
		    list = extra & 0xff;
		    incr = -1;
		    break;
		case 2:	/* static postinc */
		    list = extra & 0xff;
		    incr = 1;
		    break;
		case 1:	/* dynamic pred */
		case 3:	/* dynamic postinc */
		   abort();
		}
		if (incr < 0) { /* Predecrement */
			for (reg = 7; reg >= 0; reg--) {
				if (list & 0x80) {
					fmov_ext_mr((uintptr)temp_fp,reg);
					sub_l_ri(ad,4);
					mov_l_rm(S2,(uintptr)temp_fp);
					writelong_clobber(ad,S2,S3);
					sub_l_ri(ad,4);
					mov_l_rm(S2,(uintptr)temp_fp+4);
					writelong_clobber(ad,S2,S3);
					sub_l_ri(ad,4);
					mov_w_rm(S2,(uintptr)temp_fp+8);
					writeword_clobber(ad,S2,S3);
				}
				list <<= 1;
			}
		}
		else { /* Postincrement */
			for (reg = 0; reg <= 7; reg++) {
				if (list & 0x80) {
					fmov_ext_mr((uintptr)temp_fp,reg);
					mov_w_rm(S2,(uintptr)temp_fp+8);
					writeword_clobber(ad,S2,S3);
					add_l_ri(ad,4);
					mov_l_rm(S2,(uintptr)temp_fp+4);
					writelong_clobber(ad,S2,S3);
					add_l_ri(ad,4);
					mov_l_rm(S2,(uintptr)temp_fp);
					writelong_clobber(ad,S2,S3);
					add_l_ri(ad,4);
				}
				list <<= 1;
			}
		}
		if ((opcode & 0x38) == 0x18)
		    mov_l_rr((opcode & 7)+8,ad);
		if ((opcode & 0x38) == 0x20)
		    mov_l_rr((opcode & 7)+8,ad);
	    } else {
		/* FMOVEM memory->FPP */

		uae_u32 ad;
		switch ((extra >> 11) & 3) { /* Get out early if failure */
		case 0:
		case 2:
			break;
		case 1:
		case 3:
		default:
		    FAIL(1); return;
		}
		ad=comp_fp_adr (opcode);
		if (ad < 0) {
		    m68k_setpc (m68k_getpc () - 4);
		    op_illg (opcode);
		    return;
		}
		switch ((extra >> 11) & 3) {
		case 0:	/* static pred */
		    list = extra & 0xff;
		    incr = -1;
		    break;
		case 2:	/* static postinc */
		    list = extra & 0xff;
		    incr = 1;
		    break;
		case 1:	/* dynamic pred */
		case 3:	/* dynamic postinc */
			abort();
		}

		if (incr < 0) {
			// not reached
			for (reg = 7; reg >= 0; reg--) {
				if (list & 0x80) {
					sub_l_ri(ad,4);
					readlong(ad,S2,S3);
					mov_l_mr((uintptr)(temp_fp),S2);
					sub_l_ri(ad,4);
					readlong(ad,S2,S3);
					mov_l_mr((uintptr)(temp_fp)+4,S2);
					sub_l_ri(ad,4);
					readword(ad,S2,S3);
					mov_w_mr(((uintptr)temp_fp)+8,S2);
					fmov_ext_rm(reg,(uintptr)(temp_fp));
				}
				list <<= 1;
			}
		}
		else {
			for (reg = 0; reg <= 7; reg++) {
				if (list & 0x80) {
					readword(ad,S2,S3);
					mov_w_mr(((uintptr)temp_fp)+8,S2);
					add_l_ri(ad,4);
					readlong(ad,S2,S3);
					mov_l_mr((uintptr)(temp_fp)+4,S2);
					add_l_ri(ad,4);
					readlong(ad,S2,S3);
					mov_l_mr((uintptr)(temp_fp),S2);
					add_l_ri(ad,4);
					fmov_ext_rm(reg,(uintptr)(temp_fp));
				}
				list <<= 1;
			}
		}
		if ((opcode & 0x38) == 0x18)
		    mov_l_rr((opcode & 7)+8,ad);
		if ((opcode & 0x38) == 0x20)
		    mov_l_rr((opcode & 7)+8,ad);
	    }
	}
示例#21
0
/*
  	This function saves the state of the calculator.
  	Can be called at any time.

  	Return an error code if an error occured, 0 otherwise
*/
int ti68k_state_save(const char *filename)
{
  	FILE *f;
  	IMG_INFO *img = &img_infos;
    SAV_INFO sav;
	int i;
	long len;
	long bkpts_size;
  
  	if(!strlen(filename))
  		return ERR_CANT_OPEN_STATE;
  
  	// Open file
  	tiemu_info(_("saving state image (TiEmu v2.00 format): %s"), filename);
  	f = fopen(filename, "wb");
  	if(f == NULL)
  		return ERR_CANT_OPEN_STATE;
  	
  	// Save current image infos
	fwrite(img, 1, sizeof(IMG_INFO), f);

    // Fill state image infos
	sav.revision = SAV_REVISION;
	sav.size = sizeof(SAV_INFO);

    sav.regs_offset = sizeof(IMG_INFO) + sizeof(SAV_INFO);
    sav.io_offset = sav.regs_offset + sizeof(regs);
    sav.ram_offset = sav.io_offset + tihw.io_size + tihw.io2_size + tihw.io3_size;
	sav.misc_offset = sav.ram_offset + tihw.ram_size;
	sav.rom_offset = sav.misc_offset + sizeof(Ti68kHardware);
    sav.bkpts_offset = sav.rom_offset + wsm.nblocks*sizeof(int) + hw_flash_nblocks()*65536;

	bkpts_size = 
		g_list_length(bkpts.code) * sizeof(long) + sizeof(long) +
		g_list_length(bkpts.exception) * sizeof(long) + sizeof(long) +
		g_list_length(bkpts.pgmentry) * sizeof(long) + sizeof(long) +
		g_list_length(bkpts.mem_rb) * sizeof(long) + sizeof(long) +
		g_list_length(bkpts.mem_rw) * sizeof(long) + sizeof(long) +
		g_list_length(bkpts.mem_rl) * sizeof(long) + sizeof(long) +
		g_list_length(bkpts.mem_wb) * sizeof(long) + sizeof(long) +
		g_list_length(bkpts.mem_ww) * sizeof(long) + sizeof(long) +
		g_list_length(bkpts.mem_wl) * sizeof(long) + sizeof(long) +
		g_list_length(bkpts.mem_rng_r) * sizeof(ADDR_RANGE) + sizeof(long) +
		g_list_length(bkpts.mem_rng_w) * sizeof(ADDR_RANGE) + sizeof(long) +
		g_list_length(bkpts.bits) * sizeof(ADDR_BIT) + sizeof(long)
		;

	sav.str_offset = sav.bkpts_offset + bkpts_size;

    fwrite(&sav, 1, sizeof(SAV_INFO), f);
	
	// Update UAE structures
    MakeSR();
    m68k_setpc(m68k_getpc());
    
    // Save registers and special flags
    fwrite(&regs, sizeof(regs), 1, f);
    
    // Save I/O ports state
    fwrite(tihw.io , tihw.io_size, 1, f);
    fwrite(tihw.io2, tihw.io2_size, 1, f);
	fwrite(tihw.io3, tihw.io3_size, 1, f);	
    
    // Save RAM content
    fwrite(tihw.ram, tihw.ram_size, 1, f);

	// Save misc informations
	rtc3_state_save();
	fwrite(&tihw, sizeof(Ti68kHardware), 1, f);

	// Save modified FLASH segments
	for(i=0; i<wsm.nblocks; i++)
    {
		fwrite(&wsm.changed[i], sizeof(int), 1, f);
		if(wsm.changed[i])
			fwrite(&tihw.rom[i<<16], 1, 65536, f);
    }

    // Save breakpoints
    save_bkpt(f, bkpts.code);
    save_bkpt(f, bkpts.exception);
	save_bkpt(f, bkpts.pgmentry);

    save_bkpt(f, bkpts.mem_rb);
	save_bkpt(f, bkpts.mem_rw);
	save_bkpt(f, bkpts.mem_rl);
	save_bkpt(f, bkpts.mem_wb);
	save_bkpt(f, bkpts.mem_ww);
	save_bkpt(f, bkpts.mem_wl);

    save_bkpt2(f, bkpts.mem_rng_r);
	save_bkpt2(f, bkpts.mem_rng_w);

	save_bkpt3(f, bkpts.bits);

	// Save image location associated with this state image
	len = strlen(params.rom_file) + 1;
	fwrite(&len, 1, sizeof(len), f);
	fwrite(params.rom_file, len, 1, f);
	
	len = strlen(params.tib_file) + 1;
	fwrite(&len, 1, sizeof(len), f);
	fwrite(params.tib_file, len, 1, f);
    
    fclose(f);

  	return 0;
}
示例#22
0
文件: traps.c 项目: patope/PUAE
static void copyfromcpucontext(struct TrapCPUContext *cpu, uae_u32 pc)
{
	memcpy (regs.regs, cpu->regs, sizeof (regs.regs));
	regs.intmask = cpu->intmask;
	m68k_setpc (pc);
}