⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 star.c

📁 著名ARC模拟器源码,包括多个平台
💻 C
📖 第 1 页 / 共 5 页
字号:
/*** This will make edi _very_ negative... far enough negative that the** leftover cycle incorporation at the end of s68000exec() shouldn't be** enough to make it positive.*/static void force_context_switch(void) {	emit("sub edi,[__cycles_needed]\n");	emit("mov dword[__cycles_needed],0\n");}/*** Put all the unused cycles in the leftover cycle bank, so we can call** attention to the tricky bit processor.*/static void force_trickybit_process(void) {	emit("inc edi\n");	emit("add [__cycles_leftover],edi\n");	emit("or edi,byte -1\n");/* smaller than a mov */}/* "newpc" has been renamed to this */void perform_cached_rebase(void);/* Copy either __s_* or __u_* memory map pointers */static void copy_memory_map(char *map, char *reg) {	emit("mov %s,[__%s_fetch]\n", reg, map);	emit("mov [__fetch],%s\n", reg);	if(cputype < 68020) {		emit("mov %s,[__%s_readbyte]\n" , reg, map);		emit("mov [__readbyte],%s\n" , reg);		emit("mov %s,[__%s_readword]\n" , reg, map);		emit("mov [__readword],%s\n" , reg);		emit("mov %s,[__%s_writebyte]\n", reg, map);		emit("mov [__writebyte],%s\n", reg);		emit("mov %s,[__%s_writeword]\n", reg, map);		emit("mov [__writeword],%s\n", reg);	} else {		emit("mov %s,[__%s_readbus]\n"  , reg, map);		emit("mov [__readbus],%s\n"  , reg);		emit("mov %s,[__%s_writebus]\n" , reg, map);		emit("mov [__writebus],%s\n" , reg);	}}/***************************************************************************/static void gen_interface(void) {	emit("section .text\n");	emit("bits 32\n");	emit("top:\n");/***************************************************************************//***  s680x0init()****  Entry: Nothing**  Exit:  Zero****  This must be called before anything else.  It decompresses the main jump**  table (and loop info, in the case of the 68010).*/	begin_source_proc("init");	emit("pushad\n");	emit("mov edi,__jmptbl\n");	emit("mov esi,__jmptblcomp\n");	if(cputype == 68010) {		emit("mov ebx,__looptbl\n");	}	emit(".decomp:\n");	emit("lodsd\n");	emit("mov ecx,eax\n");	emit("and eax,0FFFFFFh\n");	emit("shr ecx,24\n");	emit("add eax,top\n");	emit("inc ecx\n");	if(cputype == 68010) {		emit("mov ebp,ecx\n");	}	emit(".jloop:\n");	emit("mov [edi],eax\n");	emit("add edi,byte 4\n");	emit("dec ecx\n");	emit("jnz short .jloop\n");	if(cputype == 68010) {		emit("lodsb\n");		emit(".lloop:\n");		emit("mov [ebx],al\n");		emit("inc ebx\n");		emit("dec ebp\n");		emit("jnz short .lloop\n");	}	emit("cmp edi,__jmptbl+262144\n");	emit("jne short .decomp\n");	emit("popad\n");	emit("xor eax,eax\n");	emit("ret\n");/***************************************************************************//***  s680x0exec(cycles)****  Entry: EAX = # cycles to execute**  Exit:  80000000h:  success**         80000001h:  PC out of range**         80000002h:  unsupported stack frame**         FFFFFFFFh:  CPU is dead because of a double fault**       < 80000000h:  invalid instruction = address of invalid instr.*/	begin_source_proc("exec");	if(use_stack) emit("mov eax,[esp+4]\n");	/*	** Check for stopped and double-faulted states.	*/	emit("test byte[__interrupts],1\n");	emit("jz .notstopped\n");	emit("test byte[__pc],1\n");	emit("jz .notfaulted\n");	emit("or eax,byte -1\n");	emit("ret\n");	emit(".notfaulted:\n");	emit("add [__odometer],eax\n");	emit("mov eax,80000000h\n");	emit("ret\n");	emit(".notstopped:\n");	emit("push ebp\n");	emit("push ebx\n");	emit("push ecx\n");	emit("push edx\n");	emit("push esi\n");	emit("push edi\n");	emit("mov [__cycles_needed],eax\n");	emit("mov edi,eax\n");/* store # of cycles to execute */	emit("dec edi\n");	emit("xor ebx,ebx\n");	emit("mov esi,[__pc]\n");	cache_ccr();	emit("xor ebp,ebp\n");	emit("mov byte[__execinfo],1\n");	/*	** Force an uncached re-base.	** This fulfills the "Entry to s680x0exec()" case.	*/	emit("call basefunction\n");	emit("add esi,ebp\n");	emit("test byte[__execinfo],2\n"); /* Check for PC out of bounds */	emit("jnz near exec_bounderror\n");	emit("mov dword[__cycles_leftover],0\n");/* an extra precaution */	/* PPL and Trace checkpoint */	emit("exec_checkpoint:\n");	emit("js short execquit\n");	/* Check PPL */	emit("mov cl,[__sr+1]\n");	emit("and ecx,byte 7\n");	emit("inc ecx\n");	emit("mov ch,[__interrupts]\n");	emit("or ch,ch\n");	emit("js short .yesint\n");	emit("shr ch,cl\n");	emit("jz short .noint\n");	emit(".yesint:\n");	emit("call flush_interrupts\n");	/* Force an uncached re-base */	emit("call basefunction\n");	emit("add esi,ebp\n");	emit("test byte[__execinfo],2\n"); /* Check for PC out of bounds */	emit("jnz near exec_bounderror\n");	emit(".noint:\n");	/*	** If the SR Trace flag is set, generate a pending trace exception.	*/	emit("mov ch,[__sr+1]\n");	emit("and ch,80h\n"); /* isolate trace flag */	emit("mov [__trace_trickybit],ch\n");	emit("jz short execloop\n");	/*	** Activate the tricky bit processor.	**	** Because edi isn't checked for negativity before entering the	** fetch/decode/execute loop, we're guaranteed to execute at least	** one more instruction before any trace exception.	**	** If another group 1 exception happens in the course of executing	** this next instruction, then the group_1_exception routine will	** clear the trace tricky bit and re-adjust the cycle counters, and	** we'll pretend none of this ever happened.	*/	force_trickybit_process();	emit("execloop:\n");/*	emit("xor ebx,ebx\n");suffice to say, bits 16-31 should be zero... */	emit("mov bx,[esi]\n");	emit("add esi,byte 2\n");	emit("jmp dword[__jmptbl+ebx*4]\n");	/* Traditional loop - used when hog mode is off */	if(!hog) {		emit("execend:\n");		emit("jns short execloop\n");	}	emit("execquit:\n");	/*	** Tricky Bit Processor	*/	/* Look for trace tricky bit */	emit("cmp byte[__trace_trickybit],0\n");	emit("je short execquit_notrace\n");	/* Generate trace exception */	emit("mov edx,24h\n");	emit("call group_1_exception\n");	perform_cached_rebase();	/* Subtract time used by exception processing */	emit("sub edi,byte %d\n", (cputype == 68010) ? 38 : 34);	emit("execquit_notrace:\n");	/*	** Look for pending interrupts that exceed the current PPL.  These	** are higher priority and are therefore processed last (the ISR will	** end up getting control).	*/	emit("mov cl,[__sr+1]\n");	emit("and ecx,byte 7\n");	emit("inc ecx\n");	emit("mov ch,[__interrupts]\n");	emit("or ch,ch\n");	emit("js short execquit_yesinterrupt\n");	emit("shr ch,cl\n");	emit("jz short execquit_nointerrupt\n");	emit("execquit_yesinterrupt:\n");	emit("call flush_interrupts\n");	/*	** Force an uncached re-base.	** This fulfills the "Hardware interrupt" case.	*/	emit("call basefunction\n");	emit("add esi,ebp\n");	emit("test byte[__execinfo],2\n"); /* Check for PC out of bounds */	emit("jnz short exec_bounderror\n");	emit("execquit_nointerrupt:\n");	/*	** Incorporate leftover cycles (if any) and see if we should keep	** running.	*/	emit("add edi,[__cycles_leftover]\n");	emit("mov dword[__cycles_leftover],0\n");	emit("jns short execloop\n");	/* Leave s680x0exec with "Success" code. */	emit("mov ecx,80000000h\n");	/*	** Exit the s680x0exec routine.  By this time the return code should	** already be in ecx.	*/	emit("execexit:\n");	emit("sub esi,ebp\n");	writeback_ccr();	emit("mov [__pc],esi\n");	emit("inc edi\n");	emit("mov edx,[__cycles_needed]\n");	emit("sub edx,edi\n");	emit("add [__odometer],edx\n");	emit("mov byte[__execinfo],0\n");	/*	** Remember: __io_cycle_counter is always -1 when idle!	**	** This prevents us from having to check __execinfo during the	** readOdometer / tripOdometer calls.	*/	emit("mov dword[__cycles_needed],0\n");	emit("mov dword[__io_cycle_counter],-1\n");	emit("mov eax,ecx\n");/* return code */	emit("pop edi\n");	emit("pop esi\n");	emit("pop edx\n");	emit("pop ecx\n");	emit("pop ebx\n");	emit("pop ebp\n");	emit("ret\n");	/*	** Leave s680x0exec with "Out of bounds" code.	*/	emit("exec_bounderror:\n");	emit("mov ecx,80000001h\n");	emit("jmp short execexit\n");	/*	** Invalid instruction handler	*/	emit("invalidins:\n");	emit("sub esi,byte 2\n");  /* back up one word */	emit("mov ecx,esi\n");/* get address in ecx */	emit("sub ecx,ebp\n");/* subtract base */	maskaddress("ecx");	if(addressbits == 32) {		emit("and ecx,7FFFFFFFh\n");	}/*	emit("or byte[__stopped],2\n");*/	emit("jmp short execexit\n");/***************************************************************************//***  s680x0reset()****  Entry: Nothing**  Exit:  0 on success**         1 on failure:**           * if there's no Supervisor Program entry for address 0**           * if s680x0exec() is active**        -1 on double fault*/	begin_source_proc("reset");	emit("mov eax,1\n");	emit("test [__execinfo],al\n"); /* Ensure s680x0exec() inactive */	emit("jnz near .return\n");	emit("cmp dword[__s_fetch],0\n");	emit("je near .return\n");	emit("dec eax\n");	emit("mov [__execinfo],al\n");	emit("sub eax,byte 16\n");	emit(".gp:\n");	emit("mov dword[__reg+64+eax*4],0\n");	emit("inc eax\n");	emit("jnz short .gp\n");	emit("mov [__asp],eax\n");	if(cputype >= 68020) emit("mov [__xsp],eax\n");	/* Set up SR for no tracing, supervisor mode, ISP, PPL 7 */	emit("mov word[__sr],2700h\n");	if(cputype >= 68010) {		emit("mov [__vbr],eax\n");		emit("mov [__sfc],al\n");		emit("mov [__dfc],al\n");	}	if(cputype == 68010) {		emit("mov [__loopmode],al\n"); 	}	/* Copy supervisor address space information */	copy_memory_map("s", "eax");	/* Generate Supervisor Program Space reads to get the initial PC and	** SSP/ISP */	emit("mov eax,1\n"); /* assume failure */	emit("mov [__pc],eax\n");	emit("mov [__interrupts],al\n");	emit("push esi\n");	emit("push ebp\n");	emit("xor esi,esi\n");	emit("call basefunction\n");/* will preserve eax */	emit("test byte[__execinfo],2\n");	emit("jnz short .exit\n");	emit("add esi,ebp\n");	emit("mov eax,[esi]\n");	emit("rol eax,16\n");	emit("mov [__a7],eax\n");	emit("mov eax,[esi+4]\n");	emit("rol eax,16\n");	emit("mov [__pc],eax\n");	/* An address error here will cause a double fault */	emit("and eax,byte 1\n");	emit("mov [__interrupts],al\n");	emit("neg eax\n"); /* -1 on double fault, 0 on success */	emit(".exit:\n");	emit("pop ebp\n");	emit("pop esi\n");	emit(".return:\n");	emit("ret\n");/***************************************************************************//***  s680x0interrupt(level, vector)****  Entry: EAX = interrupt level**         EDX = vector (-1 for auto, -2 for spurious)**  Exit:  EAX = 0 on success**               1 on failure, previous vector exists**               2 on invalid input*/	begin_source_proc("interrupt");	emit("push edx\n");	if(use_stack) {		emit("mov eax,[esp+8]\n");  /* eax = level  */		emit("mov edx,[esp+12]\n"); /* edx = vector */	}	/*	** Verify parameters.	*/	emit("cmp eax,byte 7\n");	emit("ja short .badinput\n");	emit("or eax,eax\n");	emit("jz short .badinput\n");	emit("cmp edx,255\n");	emit("jg short .badinput\n");	emit("cmp edx,byte -2\n");	emit("jl short .badinput\n");	/*	** Calculate the vector number.	*/	emit("jne short .notspurious\n");	emit("mov edx,18h\n");	emit(".notspurious:\n");	emit("or edx,edx\n");	emit("jns short .notauto\n");	emit("lea edx,[eax+18h]\n");	emit(".notauto:\n");	/*	** Test to see if this interrupt level is already pending.	** If it is, return with failure.	*/	emit("push ecx\n");	emit("mov cl,al\n");	emit("mov ah,1\n");	emit("shl ah,cl\n");	emit("pop ecx\n");	emit("test [__interrupts],ah\n");	emit("jnz .failure\n");	/*	** Commit the given interrupt and vector number.	*/	emit("or [__interrupts],ah\n");	emit("mov ah,0\n");	emit("mov [__interrupts+eax],dl\n");	emit("and byte[__interrupts],0FEh\n");	/*	** Notify the tricky bit handler.  If we're doing this outside of	** s680x0exec(), then the notification will have no effect, because	** __io_cycle_counter is always -1 when idle.	*/	emit("mov edx,[__io_cycle_counter]\n");	emit("inc edx\n");	emit("add [__cycles_leftover],edx\n");	emit("mov dword[__io_cycle_counter],-1\n");	/*	** Success (0)	*/	emit("pop edx\n");	emit("xor eax,eax\n");	emit("ret\n");	/*	** Failure (1)	*/	emit(".failure:\n");	emit("pop edx\n");	emit("mov eax,1\n");	emit("ret\n");	/*	** Bad input (2)	*/	emit(".badinput:\n");	emit("pop edx\n");	emit("mov eax,2\n");	emit("ret\n");/***************************************************************************//***  s680x0flushInterrupts()****  Flushes all pending interrupts.****  Entry: Nothing**  Exit:  Nothing*/	begin_source_proc("flushInterrupts");	/*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -