mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	added various arm modules from skyeye to make project link OK
This commit is contained in:
		
							parent
							
								
									20807c4d5a
								
							
						
					
					
						commit
						6b255111d5
					
				
					 9 changed files with 2582 additions and 166 deletions
				
			
		|  | @ -139,9 +139,14 @@ | |||
|   <ItemGroup> | ||||
|     <ClCompile Include="src\arm\armemu.cpp" /> | ||||
|     <ClCompile Include="src\arm\arminit.cpp" /> | ||||
|     <ClCompile Include="src\arm\armmmu.cpp" /> | ||||
|     <ClCompile Include="src\arm\armos.cpp" /> | ||||
|     <ClCompile Include="src\arm\armsupp.cpp" /> | ||||
|     <ClCompile Include="src\arm\armvirt.cpp" /> | ||||
|     <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" /> | ||||
|     <ClCompile Include="src\core.cpp" /> | ||||
|     <ClCompile Include="src\core_timing.cpp" /> | ||||
|     <ClCompile Include="src\elf\elf_reader.cpp" /> | ||||
|     <ClCompile Include="src\file_sys\directory_file_system.cpp" /> | ||||
|     <ClCompile Include="src\file_sys\meta_file_system.cpp" /> | ||||
|     <ClCompile Include="src\loader.cpp" /> | ||||
|  | @ -165,7 +170,8 @@ | |||
|     <ClInclude Include="src\arm\skyeye_defs.h" /> | ||||
|     <ClInclude Include="src\core.h" /> | ||||
|     <ClInclude Include="src\core_timing.h" /> | ||||
|     <ClInclude Include="src\elf\elf.h" /> | ||||
|     <ClInclude Include="src\elf\elf_reader.h" /> | ||||
|     <ClInclude Include="src\elf\elf_types.h" /> | ||||
|     <ClInclude Include="src\file_sys\directory_file_system.h" /> | ||||
|     <ClInclude Include="src\file_sys\file_sys.h" /> | ||||
|     <ClInclude Include="src\file_sys\meta_file_system.h" /> | ||||
|  |  | |||
|  | @ -22,6 +22,21 @@ | |||
|     </ClCompile> | ||||
|     <ClCompile Include="src\system.cpp" /> | ||||
|     <ClCompile Include="src\core_timing.cpp" /> | ||||
|     <ClCompile Include="src\elf\elf_reader.cpp"> | ||||
|       <Filter>elf</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="src\arm\armsupp.cpp"> | ||||
|       <Filter>arm</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="src\arm\armvirt.cpp"> | ||||
|       <Filter>arm</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="src\arm\armmmu.cpp"> | ||||
|       <Filter>arm</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="src\arm\armos.cpp"> | ||||
|       <Filter>arm</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Filter Include="arm"> | ||||
|  | @ -94,7 +109,10 @@ | |||
|     </ClInclude> | ||||
|     <ClInclude Include="src\system.h" /> | ||||
|     <ClInclude Include="src\core_timing.h" /> | ||||
|     <ClInclude Include="src\elf\elf.h"> | ||||
|     <ClInclude Include="src\elf\elf_reader.h"> | ||||
|       <Filter>elf</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="src\elf\elf_types.h"> | ||||
|       <Filter>elf</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|  |  | |||
|  | @ -21,6 +21,19 @@ | |||
| #include "armemu.h" | ||||
| #include "armos.h" | ||||
| 
 | ||||
| void | ||||
| XScale_set_fsr_far(ARMul_State * state, ARMword fsr, ARMword _far) | ||||
| { | ||||
| 	_dbg_assert_msg_(ARM11, false, "ImplementMe: XScale_set_fsr_far!"); | ||||
| 	//if (!state->is_XScale || (read_cp14_reg(10) & (1UL << 31)) == 0)
 | ||||
| 	//	return;
 | ||||
| 	//
 | ||||
| 	//write_cp15_reg(state, 5, 0, 0, fsr);
 | ||||
| 	//write_cp15_reg(state, 6, 0, 0, _far);
 | ||||
| } | ||||
| 
 | ||||
| #define ARMul_Debug(x,y,z) 0 // Disabling this /bunnei
 | ||||
| 
 | ||||
| //#include "skyeye_callback.h"
 | ||||
| //#include "skyeye_bus.h"
 | ||||
| //#include "sim_control.h"
 | ||||
|  | @ -2174,10 +2187,10 @@ ARMul_Emulate26 (ARMul_State * state) | |||
| 								(state, | ||||
| 								 ARMul_CP15_R5_MMU_EXCPT, | ||||
| 								 pc); | ||||
| 							if (!XScale_debug_moe | ||||
| 							    (state, | ||||
| 							     ARMul_CP14_R10_MOE_BT)) | ||||
| 								break; | ||||
| 							//if (!XScale_debug_moe
 | ||||
| 							//    (state,
 | ||||
| 							//     ARMul_CP14_R10_MOE_BT))
 | ||||
| 							//	break; // Disabled /bunnei
 | ||||
| 						} | ||||
| 
 | ||||
| 						/* Force the next instruction to be refetched.  */ | ||||
|  |  | |||
|  | @ -73,6 +73,7 @@ extern ARMword isize; | |||
| #define ASSIGNT(res) state->TFlag = res | ||||
| #define INSN_SIZE (TFLAG ? 2 : 4) | ||||
| #else | ||||
| #define TBIT (1L << 5) | ||||
| #define INSN_SIZE 4 | ||||
| #define TFLAG 0 | ||||
| #endif | ||||
|  | @ -229,12 +230,12 @@ extern ARMword isize; | |||
|     }									\ | ||||
|   while (0) | ||||
| 
 | ||||
| #ifndef MODE32 | ||||
| //#ifndef MODE32
 | ||||
| #define VECTORS 0x20 | ||||
| #define LEGALADDR 0x03ffffff | ||||
| #define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig) | ||||
| #define ADDREXCEPT(address)   (address > LEGALADDR && !state->data32Sig) | ||||
| #endif | ||||
| //#endif
 | ||||
| 
 | ||||
| #define INTERNALABORT(address)			\ | ||||
|   do						\ | ||||
|  | @ -409,10 +410,12 @@ extern ARMword isize; | |||
|      || (! (STATE)->is_XScale)				\ | ||||
|      || (read_cp15_reg (15, 0, 1) & (1 << (CP)))) | ||||
| */ | ||||
| #define CP_ACCESS_ALLOWED(STATE, CP)			\ | ||||
|     (   ((CP) >= 14)					\ | ||||
|      || (! (STATE)->is_XScale)				\ | ||||
|      || (xscale_cp15_cp_access_allowed(STATE,15,CP))) | ||||
| //#define CP_ACCESS_ALLOWED(STATE, CP)			\ | ||||
| //	(((CP) >= 14)					\ | ||||
| //	|| (!(STATE)->is_XScale)				\ | ||||
| //	|| (xscale_cp15_cp_access_allowed(STATE, 15, CP)))
 | ||||
| 
 | ||||
| #define CP_ACCESS_ALLOWED(STATE, CP) false // Disabled coprocessor shit /bunnei
 | ||||
| 
 | ||||
| /* Macro to rotate n right by b bits.  */ | ||||
| #define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b)))) | ||||
|  |  | |||
|  | @ -271,7 +271,7 @@ below line sould be in skyeye_mach_XXX.c 's XXX_mach_init function | |||
| 
 | ||||
| 	/* Only initialse the coprocessor support once we
 | ||||
| 	   know what kind of chip we are dealing with.  */ | ||||
| 	ARMul_CoProInit (state); | ||||
| 	//ARMul_CoProInit (state); Commented out /bunnei
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  | @ -318,7 +318,7 @@ ARMul_Reset (ARMul_State * state) | |||
| 	state->NumFcycles = 0; | ||||
| 
 | ||||
| 	//fprintf(stderr,"armul_reset 3: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);  
 | ||||
| 	mmu_reset (state); | ||||
| 	//mmu_reset (state); Commented out /bunnei
 | ||||
| 	//fprintf(stderr,"armul_reset 4: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);  
 | ||||
| 
 | ||||
| 	//mem_reset (state); /* move to memory/ram.c */
 | ||||
|  | @ -436,7 +436,8 @@ ARMul_DoProg (ARMul_State * state) | |||
| 		} | ||||
| 
 | ||||
| 		else { | ||||
| 			pc = ARMul_Emulate26 (state); | ||||
| 			//pc = ARMul_Emulate26 (state); Commented out /bunnei
 | ||||
| 			ERROR_LOG(ARM11, "Unsupported ARM 26-bit Mode!"); | ||||
| 		} | ||||
| 		//chy 2006-02-22, should test debugmode first
 | ||||
| 		//chy 2006-04-14, put below codes in ARMul_Emulate
 | ||||
|  | @ -489,8 +490,10 @@ ARMul_DoInstr (ARMul_State * state) | |||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	else | ||||
| 		pc = ARMul_Emulate26 (state); | ||||
| 	else { | ||||
| 		//pc = ARMul_Emulate26 (state); Commented out /bunnei
 | ||||
| 		ERROR_LOG(ARM11, "Unsupported ARM 26-bit Mode!"); | ||||
| 	} | ||||
| 
 | ||||
| 	return (pc); | ||||
| } | ||||
|  | @ -501,78 +504,78 @@ ARMul_DoInstr (ARMul_State * state) | |||
| * appropriate vector's memory address (0,4,8 ....)                          * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| //void
 | ||||
| //ARMul_Abort (ARMul_State * state, ARMword vector)
 | ||||
| //{
 | ||||
| //	ARMword temp;
 | ||||
| //	int isize = INSN_SIZE;
 | ||||
| //	int esize = (TFLAG ? 0 : 4);
 | ||||
| //	int e2size = (TFLAG ? -4 : 0);
 | ||||
| //
 | ||||
| //	state->Aborted = FALSE;
 | ||||
| //
 | ||||
| //	if (state->prog32Sig)
 | ||||
| //		if (ARMul_MODE26BIT)
 | ||||
| //			temp = R15PC;
 | ||||
| //		else
 | ||||
| //			temp = state->Reg[15];
 | ||||
| //	else
 | ||||
| //		temp = R15PC | ECC | ER15INT | EMODE;
 | ||||
| //
 | ||||
| //	switch (vector) {
 | ||||
| //	case ARMul_ResetV:	/* RESET */
 | ||||
| //		SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE,
 | ||||
| //			  0);
 | ||||
| //		break;
 | ||||
| //	case ARMul_UndefinedInstrV:	/* Undefined Instruction */
 | ||||
| //		SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE,
 | ||||
| //			  isize);
 | ||||
| //		break;
 | ||||
| //	case ARMul_SWIV:	/* Software Interrupt */
 | ||||
| //		SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE,
 | ||||
| //			  isize);
 | ||||
| //		break;
 | ||||
| //	case ARMul_PrefetchAbortV:	/* Prefetch Abort */
 | ||||
| //		state->AbortAddr = 1;
 | ||||
| //		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE,
 | ||||
| //			  esize);
 | ||||
| //		break;
 | ||||
| //	case ARMul_DataAbortV:	/* Data Abort */
 | ||||
| //		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE,
 | ||||
| //			  e2size);
 | ||||
| //		break;
 | ||||
| //	case ARMul_AddrExceptnV:	/* Address Exception */
 | ||||
| //		SETABORT (IBIT, SVC26MODE, isize);
 | ||||
| //		break;
 | ||||
| //	case ARMul_IRQV:	/* IRQ */
 | ||||
| //		//chy 2003-09-02 the if sentence seems no use
 | ||||
| //#if 0
 | ||||
| //		if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp)
 | ||||
| //		    || (temp & ARMul_CP13_R0_IRQ))
 | ||||
| //#endif
 | ||||
| //			SETABORT (IBIT,
 | ||||
| //				  state->prog32Sig ? IRQ32MODE : IRQ26MODE,
 | ||||
| //				  esize);
 | ||||
| //		break;
 | ||||
| //	case ARMul_FIQV:	/* FIQ */
 | ||||
| //		//chy 2003-09-02 the if sentence seems no use
 | ||||
| //#if 0
 | ||||
| //		if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp)
 | ||||
| //		    || (temp & ARMul_CP13_R0_FIQ))
 | ||||
| //#endif
 | ||||
| //			SETABORT (INTBITS,
 | ||||
| //				  state->prog32Sig ? FIQ32MODE : FIQ26MODE,
 | ||||
| //				  esize);
 | ||||
| //		break;
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	if (ARMul_MODE32BIT) {
 | ||||
| //		if (state->mmu.control & CONTROL_VECTOR)
 | ||||
| //			vector += 0xffff0000;	//for v4 high exception  address
 | ||||
| //		if (state->vector_remap_flag)
 | ||||
| //			vector += state->vector_remap_addr; /* support some remap function in LPC processor */
 | ||||
| //		ARMul_SetR15 (state, vector);
 | ||||
| //	}
 | ||||
| //	else
 | ||||
| //		ARMul_SetR15 (state, R15CCINTMODE | vector);
 | ||||
| //}
 | ||||
| void | ||||
| ARMul_Abort (ARMul_State * state, ARMword vector) | ||||
| { | ||||
| 	ARMword temp; | ||||
| 	int isize = INSN_SIZE; | ||||
| 	int esize = (TFLAG ? 0 : 4); | ||||
| 	int e2size = (TFLAG ? -4 : 0); | ||||
| 
 | ||||
| 	state->Aborted = FALSE; | ||||
| 
 | ||||
| 	if (state->prog32Sig) | ||||
| 		if (ARMul_MODE26BIT) | ||||
| 			temp = R15PC; | ||||
| 		else | ||||
| 			temp = state->Reg[15]; | ||||
| 	else | ||||
| 		temp = R15PC | ECC | ER15INT | EMODE; | ||||
| 
 | ||||
| 	switch (vector) { | ||||
| 	case ARMul_ResetV:	/* RESET */ | ||||
| 		SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE, | ||||
| 			  0); | ||||
| 		break; | ||||
| 	case ARMul_UndefinedInstrV:	/* Undefined Instruction */ | ||||
| 		SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE, | ||||
| 			  isize); | ||||
| 		break; | ||||
| 	case ARMul_SWIV:	/* Software Interrupt */ | ||||
| 		SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE, | ||||
| 			  isize); | ||||
| 		break; | ||||
| 	case ARMul_PrefetchAbortV:	/* Prefetch Abort */ | ||||
| 		state->AbortAddr = 1; | ||||
| 		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, | ||||
| 			  esize); | ||||
| 		break; | ||||
| 	case ARMul_DataAbortV:	/* Data Abort */ | ||||
| 		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, | ||||
| 			  e2size); | ||||
| 		break; | ||||
| 	case ARMul_AddrExceptnV:	/* Address Exception */ | ||||
| 		SETABORT (IBIT, SVC26MODE, isize); | ||||
| 		break; | ||||
| 	case ARMul_IRQV:	/* IRQ */ | ||||
| 		//chy 2003-09-02 the if sentence seems no use
 | ||||
| #if 0 | ||||
| 		if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) | ||||
| 		    || (temp & ARMul_CP13_R0_IRQ)) | ||||
| #endif | ||||
| 			SETABORT (IBIT, | ||||
| 				  state->prog32Sig ? IRQ32MODE : IRQ26MODE, | ||||
| 				  esize); | ||||
| 		break; | ||||
| 	case ARMul_FIQV:	/* FIQ */ | ||||
| 		//chy 2003-09-02 the if sentence seems no use
 | ||||
| #if 0 | ||||
| 		if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) | ||||
| 		    || (temp & ARMul_CP13_R0_FIQ)) | ||||
| #endif | ||||
| 			SETABORT (INTBITS, | ||||
| 				  state->prog32Sig ? FIQ32MODE : FIQ26MODE, | ||||
| 				  esize); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ARMul_MODE32BIT) { | ||||
| 		if (state->mmu.control & CONTROL_VECTOR) | ||||
| 			vector += 0xffff0000;	//for v4 high exception  address
 | ||||
| 		if (state->vector_remap_flag) | ||||
| 			vector += state->vector_remap_addr; /* support some remap function in LPC processor */ | ||||
| 		ARMul_SetR15 (state, vector); | ||||
| 	} | ||||
| 	else | ||||
| 		ARMul_SetR15 (state, R15CCINTMODE | vector); | ||||
| } | ||||
|  |  | |||
|  | @ -45,55 +45,51 @@ mmu_init (ARMul_State * state) | |||
| 	state->mmu.process_id = 0; | ||||
| 
 | ||||
| 	switch (state->cpu->cpu_val & state->cpu->cpu_mask) { | ||||
| 	case SA1100: | ||||
| 	case SA1110: | ||||
| 		SKYEYE_INFO("SKYEYE: use sa11xx mmu ops\n"); | ||||
| 		state->mmu.ops = sa_mmu_ops; | ||||
| 		break; | ||||
| 	case PXA250: | ||||
| 	case PXA270:		//xscale
 | ||||
| 		SKYEYE_INFO ("SKYEYE: use xscale mmu ops\n"); | ||||
| 		state->mmu.ops = xscale_mmu_ops; | ||||
| 		break; | ||||
| 	case 0x41807200:	//arm720t
 | ||||
| 	case 0x41007700:	//arm7tdmi
 | ||||
| 	case 0x41007100:	//arm7100
 | ||||
| 		SKYEYE_INFO ( "SKYEYE: use arm7100 mmu ops\n"); | ||||
| 		state->mmu.ops = arm7100_mmu_ops; | ||||
| 		break; | ||||
| 	case 0x41009200: | ||||
| 		SKYEYE_INFO ("SKYEYE: use arm920t mmu ops\n"); | ||||
| 		state->mmu.ops = arm920t_mmu_ops; | ||||
| 		break; | ||||
| 	case 0x41069260: | ||||
| 		SKYEYE_INFO ("SKYEYE: use arm926ejs mmu ops\n"); | ||||
| 		state->mmu.ops = arm926ejs_mmu_ops; | ||||
| 		break; | ||||
| 	//case SA1100:
 | ||||
| 	//case SA1110:
 | ||||
| 	//	NOTICE_LOG(ARM11, "SKYEYE: use sa11xx mmu ops\n");
 | ||||
| 	//	state->mmu.ops = sa_mmu_ops;
 | ||||
| 	//	break;
 | ||||
| 	//case PXA250:
 | ||||
| 	//case PXA270:		//xscale
 | ||||
| 	//	NOTICE_LOG(ARM11, "SKYEYE: use xscale mmu ops\n");
 | ||||
| 	//	state->mmu.ops = xscale_mmu_ops;
 | ||||
| 	//	break;
 | ||||
| 	//case 0x41807200:	//arm720t
 | ||||
| 	//case 0x41007700:	//arm7tdmi
 | ||||
| 	//case 0x41007100:	//arm7100
 | ||||
| 	//	NOTICE_LOG(ARM11,  "SKYEYE: use arm7100 mmu ops\n");
 | ||||
| 	//	state->mmu.ops = arm7100_mmu_ops;
 | ||||
| 	//	break;
 | ||||
| 	//case 0x41009200:
 | ||||
| 	//	NOTICE_LOG(ARM11, "SKYEYE: use arm920t mmu ops\n");
 | ||||
| 	//	state->mmu.ops = arm920t_mmu_ops;
 | ||||
| 	//	break;
 | ||||
| 	//case 0x41069260:
 | ||||
| 	//	NOTICE_LOG(ARM11, "SKYEYE: use arm926ejs mmu ops\n");
 | ||||
| 	//	state->mmu.ops = arm926ejs_mmu_ops;
 | ||||
| 	//	break;
 | ||||
| 	/* case 0x560f5810: */ | ||||
| 	case 0x0007b000: | ||||
| 		SKYEYE_INFO ("SKYEYE: use arm11jzf-s mmu ops\n"); | ||||
| 		state->mmu.ops = arm1176jzf_s_mmu_ops; | ||||
| 		NOTICE_LOG(ARM11, "SKYEYE: use arm11jzf-s mmu ops\n"); | ||||
| 		//state->mmu.ops = arm1176jzf_s_mmu_ops;
 | ||||
| 		_dbg_assert_msg_(ARM11, false, "ImplementMe: arm1176jzf_s_mmu_ops!"); | ||||
| 		break; | ||||
| 
 | ||||
| 	case 0xc090: | ||||
| 		SKYEYE_INFO ("SKYEYE: use cortex_a9 mmu ops\n"); | ||||
| 		state->mmu.ops = cortex_a9_mmu_ops; | ||||
| 		break; | ||||
| 	default: | ||||
| 		fprintf (stderr, | ||||
| 		ERROR_LOG (ARM11, | ||||
| 			 "SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n", | ||||
| 			 state->cpu->cpu_val & state->cpu->cpu_mask); | ||||
| 		skyeye_exit (-1); | ||||
| 		break; | ||||
| 
 | ||||
| 	}; | ||||
| 	ret = state->mmu.ops.init (state); | ||||
| 	state->mmu_inited = (ret == 0); | ||||
| 	/* initialize mmu_read and mmu_write for disassemble */ | ||||
| 	skyeye_config_t *config  = get_current_config(); | ||||
| 	generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name); | ||||
| 	arch_instance->mmu_read = arm_mmu_read; | ||||
| 	arch_instance->mmu_write = arm_mmu_write; | ||||
| 	//skyeye_config_t *config  = get_current_config();
 | ||||
| 	//generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name);
 | ||||
| 	//arch_instance->mmu_read = arm_mmu_read;
 | ||||
| 	//arch_instance->mmu_write = arm_mmu_write;
 | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
|  | @ -201,41 +197,43 @@ mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr) | |||
| 	return (MMU_OPS.v2p_dbct (state, virt_addr, phys_addr)); | ||||
| } | ||||
| 
 | ||||
| /* dis_mmu_read for disassemble */ | ||||
| exception_t arm_mmu_read(short size, generic_address_t addr, uint32_t * value) | ||||
| { | ||||
| 	ARMul_State *state; | ||||
| 	ARM_CPU_State *cpu = get_current_cpu(); | ||||
| 	state = &cpu->core[0]; | ||||
| 	switch(size){ | ||||
| 	case 8: | ||||
| 		MMU_OPS.read_byte (state, addr, value); | ||||
| 		break; | ||||
| 	case 16: | ||||
| 	case 32: | ||||
| 		break; | ||||
| 	default: | ||||
| 		printf("In %s error size %d Line %d\n", __func__, size, __LINE__); | ||||
| 		break; | ||||
| 	} | ||||
| 	return No_exp; | ||||
| } | ||||
| /* dis_mmu_write for disassemble */ | ||||
| exception_t arm_mmu_write(short size, generic_address_t addr, uint32_t *value) | ||||
| { | ||||
| 	ARMul_State *state; | ||||
| 	ARM_CPU_State *cpu = get_current_cpu(); | ||||
| 		state = &cpu->core[0]; | ||||
| 	switch(size){ | ||||
| 	case 8: | ||||
| 		MMU_OPS.write_byte (state, addr, value); | ||||
| 		break; | ||||
| 	case 16: | ||||
| 	case 32: | ||||
| 		break; | ||||
| 	default: | ||||
| 		printf("In %s error size %d Line %d\n", __func__, size, __LINE__); | ||||
| 		break; | ||||
| 	} | ||||
| 	return No_exp; | ||||
| } | ||||
| //
 | ||||
| //
 | ||||
| ///* dis_mmu_read for disassemble */
 | ||||
| //exception_t arm_mmu_read(short size, uint32_t addr, uint32_t * value)
 | ||||
| //{
 | ||||
| //	ARMul_State *state;
 | ||||
| //	ARM_CPU_State *cpu = get_current_cpu();
 | ||||
| //	state = &cpu->core[0];
 | ||||
| //	switch(size){
 | ||||
| //	case 8:
 | ||||
| //		MMU_OPS.read_byte (state, addr, value);
 | ||||
| //		break;
 | ||||
| //	case 16:
 | ||||
| //	case 32:
 | ||||
| //		break;
 | ||||
| //	default:
 | ||||
| //		ERROR_LOG(ARM11, "Error size %d", size);
 | ||||
| //		break;
 | ||||
| //	}
 | ||||
| //	return No_exp;
 | ||||
| //}
 | ||||
| ///* dis_mmu_write for disassemble */
 | ||||
| //exception_t arm_mmu_write(short size, uint32_t addr, uint32_t *value)
 | ||||
| //{
 | ||||
| //	ARMul_State *state;
 | ||||
| //	ARM_CPU_State *cpu = get_current_cpu();
 | ||||
| //		state = &cpu->core[0];
 | ||||
| //	switch(size){
 | ||||
| //	case 8:
 | ||||
| //		MMU_OPS.write_byte (state, addr, value);
 | ||||
| //		break;
 | ||||
| //	case 16:
 | ||||
| //	case 32:
 | ||||
| //		break;
 | ||||
| //	default:
 | ||||
| //		printf("In %s error size %d Line %d\n", __func__, size, __LINE__);
 | ||||
| //		break;
 | ||||
| //	}
 | ||||
| //	return No_exp;
 | ||||
| //}
 | ||||
|  |  | |||
							
								
								
									
										742
									
								
								src/core/src/arm/armos.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										742
									
								
								src/core/src/arm/armos.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,742 @@ | |||
| /*  armos.c -- ARMulator OS interface:  ARM6 Instruction Emulator.
 | ||||
|     Copyright (C) 1994 Advanced RISC Machines Ltd. | ||||
|   | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
|   | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|   | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||||
| 
 | ||||
| /* This file contains a model of Demon, ARM Ltd's Debug Monitor,
 | ||||
| including all the SWI's required to support the C library. The code in | ||||
| it is not really for the faint-hearted (especially the abort handling | ||||
| code), but it is a complete example. Defining NOOS will disable all the | ||||
| fun, and definign VAILDATE will define SWI 1 to enter SVC mode, and SWI | ||||
| 0x11 to halt the emulator. */ | ||||
| 
 | ||||
| //chy 2005-09-12 disable below line
 | ||||
| //#include "config.h"
 | ||||
| 
 | ||||
| #include <time.h> | ||||
| #include <errno.h> | ||||
| #include <string.h> | ||||
| #include "skyeye_defs.h" | ||||
| #ifndef __USE_LARGEFILE64 | ||||
| #define __USE_LARGEFILE64               /* When use 64 bit large file need define it! for stat64*/ | ||||
| #endif | ||||
| #include <fcntl.h> | ||||
| #include <sys/stat.h> | ||||
| 
 | ||||
| 
 | ||||
| #ifndef O_RDONLY | ||||
| #define O_RDONLY 0 | ||||
| #endif | ||||
| #ifndef O_WRONLY | ||||
| #define O_WRONLY 1 | ||||
| #endif | ||||
| #ifndef O_RDWR | ||||
| #define O_RDWR   2 | ||||
| #endif | ||||
| #ifndef O_BINARY | ||||
| #define O_BINARY 0 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __STDC__ | ||||
| #define unlink(s) remove(s) | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAVE_UNISTD_H | ||||
| #include <unistd.h>		/* For SEEK_SET etc */ | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __riscos | ||||
| extern int _fisatty (FILE *); | ||||
| #define isatty_(f) _fisatty(f) | ||||
| #else | ||||
| #ifdef __ZTC__ | ||||
| #include <io.h> | ||||
| #define isatty_(f) isatty((f)->_file) | ||||
| #else | ||||
| #ifdef macintosh | ||||
| #include <ioctl.h> | ||||
| #define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL)) | ||||
| #else | ||||
| #define isatty_(f) isatty (fileno (f)) | ||||
| #endif | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #include "armdefs.h" | ||||
| #include "armos.h" | ||||
| #include "armemu.h" | ||||
| 
 | ||||
| #ifndef NOOS | ||||
| #ifndef VALIDATE | ||||
| /* #ifndef ASIM */ | ||||
| //chy 2005-09-12 disable below line
 | ||||
| //#include "armfpe.h"
 | ||||
| /* #endif */ | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #define DUMP_SYSCALL 0 | ||||
| #define dump(...) do { if (DUMP_SYSCALL) printf(__VA_ARGS__); } while(0) | ||||
| //#define debug(...)			printf(__VA_ARGS__);
 | ||||
| #define debug(...)			; | ||||
| 
 | ||||
| extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number); | ||||
| 
 | ||||
| #ifndef FOPEN_MAX | ||||
| #define FOPEN_MAX 64 | ||||
| #endif | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                          OS private Information                           * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| unsigned arm_dyncom_SWI(ARMul_State * state, ARMword number) | ||||
| { | ||||
| 	return ARMul_OSHandleSWI(state, number); | ||||
| } | ||||
| 
 | ||||
| //mmap_area_t *mmap_global = NULL;
 | ||||
| 
 | ||||
| static int translate_open_mode[] = { | ||||
| 	O_RDONLY,		/* "r"   */ | ||||
| 	O_RDONLY + O_BINARY,	/* "rb"  */ | ||||
| 	O_RDWR,			/* "r+"  */ | ||||
| 	O_RDWR + O_BINARY,	/* "r+b" */ | ||||
| 	O_WRONLY + O_CREAT + O_TRUNC,	/* "w"   */ | ||||
| 	O_WRONLY + O_BINARY + O_CREAT + O_TRUNC,	/* "wb"  */ | ||||
| 	O_RDWR + O_CREAT + O_TRUNC,	/* "w+"  */ | ||||
| 	O_RDWR + O_BINARY + O_CREAT + O_TRUNC,	/* "w+b" */ | ||||
| 	O_WRONLY + O_APPEND + O_CREAT,	/* "a"   */ | ||||
| 	O_WRONLY + O_BINARY + O_APPEND + O_CREAT,	/* "ab"  */ | ||||
| 	O_RDWR + O_APPEND + O_CREAT,	/* "a+"  */ | ||||
| 	O_RDWR + O_BINARY + O_APPEND + O_CREAT	/* "a+b" */ | ||||
| }; | ||||
| //
 | ||||
| //static void
 | ||||
| //SWIWrite0 (ARMul_State * state, ARMword addr)
 | ||||
| //{
 | ||||
| //	ARMword temp;
 | ||||
| //
 | ||||
| //	//while ((temp = ARMul_ReadByte (state, addr++)) != 0)
 | ||||
| //	while(1){
 | ||||
| //		mem_read(8, addr++, &temp);
 | ||||
| //		if(temp != 0)
 | ||||
| //			(void) fputc ((char) temp, stdout);
 | ||||
| //		else
 | ||||
| //			break;
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //static void
 | ||||
| //WriteCommandLineTo (ARMul_State * state, ARMword addr)
 | ||||
| //{
 | ||||
| //	ARMword temp;
 | ||||
| //	char *cptr = state->CommandLine;
 | ||||
| //	if (cptr == NULL)
 | ||||
| //		cptr = "\0";
 | ||||
| //	do {
 | ||||
| //		temp = (ARMword) * cptr++;
 | ||||
| //		//ARMul_WriteByte (state, addr++, temp);
 | ||||
| //		mem_write(8, addr++, temp);
 | ||||
| //	}
 | ||||
| //	while (temp != 0);
 | ||||
| //}
 | ||||
| //
 | ||||
| //static void
 | ||||
| //SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
 | ||||
| //{
 | ||||
| //	char dummy[2000];
 | ||||
| //	int flags;
 | ||||
| //	int i;
 | ||||
| //
 | ||||
| //	for (i = 0; (dummy[i] = ARMul_ReadByte (state, name + i)); i++);
 | ||||
| //	assert(SWIflags< (sizeof(translate_open_mode)/ sizeof(translate_open_mode[0])));
 | ||||
| //	/* Now we need to decode the Demon open mode */
 | ||||
| //	flags = translate_open_mode[SWIflags];
 | ||||
| //	flags = SWIflags;
 | ||||
| //
 | ||||
| //	/* Filename ":tt" is special: it denotes stdin/out */
 | ||||
| //	if (strcmp (dummy, ":tt") == 0) {
 | ||||
| //		if (flags == O_RDONLY)	/* opening tty "r" */
 | ||||
| //			state->Reg[0] = 0;	/* stdin */
 | ||||
| //		else
 | ||||
| //			state->Reg[0] = 1;	/* stdout */
 | ||||
| //	}
 | ||||
| //	else {
 | ||||
| //		state->Reg[0] = (int) open (dummy, flags, 0666);
 | ||||
| //	}
 | ||||
| //}
 | ||||
| //
 | ||||
| //static void
 | ||||
| //SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
 | ||||
| //{
 | ||||
| //	int res;
 | ||||
| //	int i;
 | ||||
| //	char *local = (char*) malloc (len);
 | ||||
| //
 | ||||
| //	if (local == NULL) {
 | ||||
| //		fprintf (stderr,
 | ||||
| //			 "sim: Unable to read 0x%ulx bytes - out of memory\n",
 | ||||
| //			 len);
 | ||||
| //		return;
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	res = read (f, local, len);
 | ||||
| //	if (res > 0)
 | ||||
| //		for (i = 0; i < res; i++)
 | ||||
| //			//ARMul_WriteByte (state, ptr + i, local[i]);
 | ||||
| //			mem_write(8, ptr + i, local[i]);
 | ||||
| //	free (local);
 | ||||
| //	//state->Reg[0] = res == -1 ? -1 : len - res;
 | ||||
| //	state->Reg[0] = res;
 | ||||
| //}
 | ||||
| //
 | ||||
| //static void
 | ||||
| //SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
 | ||||
| //{
 | ||||
| //	int res;
 | ||||
| //	ARMword i;
 | ||||
| //	char *local = malloc (len);
 | ||||
| //
 | ||||
| //	if (local == NULL) {
 | ||||
| //		fprintf (stderr,
 | ||||
| //			 "sim: Unable to write 0x%lx bytes - out of memory\n",
 | ||||
| //			 (long unsigned int) len);
 | ||||
| //		return;
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	for (i = 0; i < len; i++){
 | ||||
| //		//local[i] = ARMul_ReadByte (state, ptr + i);
 | ||||
| //		ARMword data;
 | ||||
| //		mem_read(8, ptr + i, &data);
 | ||||
| //		local[i] = data & 0xFF;
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	res = write (f, local, len);
 | ||||
| //	//state->Reg[0] = res == -1 ? -1 : len - res;
 | ||||
| //	state->Reg[0] = res;
 | ||||
| //	free (local);
 | ||||
| //}
 | ||||
| 
 | ||||
| //static void
 | ||||
| //SWIflen (ARMul_State * state, ARMword fh)
 | ||||
| //{
 | ||||
| //	ARMword addr;
 | ||||
| //
 | ||||
| //	if (fh == 0 || fh > FOPEN_MAX) {
 | ||||
| //		state->Reg[0] = -1L;
 | ||||
| //		return;
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	addr = lseek (fh, 0, SEEK_CUR);
 | ||||
| //
 | ||||
| //	state->Reg[0] = lseek (fh, 0L, SEEK_END);
 | ||||
| //	(void) lseek (fh, addr, SEEK_SET);
 | ||||
| //
 | ||||
| //}
 | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| * The emulator calls this routine when a SWI instruction is encuntered. The * | ||||
| * parameter passed is the SWI number (lower 24 bits of the instruction).    * | ||||
| \***************************************************************************/ | ||||
| /* ahe-ykl information is retrieved from elf header and the starting value of
 | ||||
|    brk_static is in sky_info_t */ | ||||
| 
 | ||||
| /* brk static hold the value of brk */ | ||||
| static uint32_t brk_static = -1; | ||||
| 
 | ||||
| unsigned | ||||
| ARMul_OSHandleSWI (ARMul_State * state, ARMword number) | ||||
| { | ||||
| 	number &= 0xfffff; | ||||
| 	ARMword addr, temp; | ||||
| 
 | ||||
| 	switch (number) { | ||||
| //	case SWI_Syscall:
 | ||||
| //		if (state->Reg[7] != 0) 
 | ||||
| //			return ARMul_OSHandleSWI(state, state->Reg[7]);
 | ||||
| //		else
 | ||||
| //			return FALSE;
 | ||||
| //	case SWI_Read:
 | ||||
| //		SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
 | ||||
| //		return TRUE;
 | ||||
| //
 | ||||
| //	case SWI_GetUID32:
 | ||||
| //		state->Reg[0] = getuid();
 | ||||
| //		return TRUE;
 | ||||
| //
 | ||||
| //	case SWI_GetGID32:
 | ||||
| //		state->Reg[0] = getgid();
 | ||||
| //		return TRUE;
 | ||||
| //
 | ||||
| //	case SWI_GetEUID32:
 | ||||
| //		state->Reg[0] = geteuid();
 | ||||
| //		return TRUE;
 | ||||
| //
 | ||||
| //	case SWI_GetEGID32:
 | ||||
| //		state->Reg[0] = getegid();
 | ||||
| //		return TRUE;
 | ||||
| //
 | ||||
| //	case SWI_Write:
 | ||||
| //		SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
 | ||||
| //		return TRUE;
 | ||||
| //
 | ||||
| //	case SWI_Open:
 | ||||
| //		SWIopen (state, state->Reg[0], state->Reg[1]);
 | ||||
| //		return TRUE;
 | ||||
| //
 | ||||
| //	case SWI_Close:
 | ||||
| //		state->Reg[0] = close (state->Reg[0]);
 | ||||
| //		return TRUE;
 | ||||
| //
 | ||||
| //	case SWI_Seek:{
 | ||||
| //			/* We must return non-zero for failure */
 | ||||
| //			state->Reg[0] =
 | ||||
| //				lseek (state->Reg[0], state->Reg[1],
 | ||||
| //					     SEEK_SET);
 | ||||
| //			return TRUE;
 | ||||
| //		}
 | ||||
| //
 | ||||
| //	case SWI_ExitGroup:
 | ||||
| //	case SWI_Exit:
 | ||||
| //		{
 | ||||
| //		struct timeval tv;
 | ||||
| //		//gettimeofday(&tv,NULL);
 | ||||
| //		//printf("In %s, %d  sec, %d usec\n", __FUNCTION__, tv.tv_sec, tv.tv_usec);
 | ||||
| //		printf("passed %d sec, %lld usec\n", get_clock_sec(), get_clock_us());
 | ||||
| //
 | ||||
| //		/* quit here */
 | ||||
| //		run_command("quit");
 | ||||
| //		return TRUE;
 | ||||
| //		}
 | ||||
| //	case SWI_Times:{
 | ||||
| //		uint32_t dest = state->Reg[0];
 | ||||
| //		struct tms now;
 | ||||
| //		struct target_tms32 nowret;
 | ||||
| //
 | ||||
| //		uint32_t ret = times(&now);
 | ||||
| //
 | ||||
| //		if (ret == -1){
 | ||||
| //			debug("syscall %s error %d\n", "SWI_Times", ret);
 | ||||
| //			state->Reg[0] = ret;
 | ||||
| //			return FALSE;
 | ||||
| //		}
 | ||||
| //		
 | ||||
| //		nowret.tms_cstime = now.tms_cstime;
 | ||||
| //		nowret.tms_cutime = now.tms_cutime;
 | ||||
| //		nowret.tms_stime = now.tms_stime;
 | ||||
| //		nowret.tms_utime = now.tms_utime;
 | ||||
| //
 | ||||
| //		uint32_t offset;
 | ||||
| //		for (offset = 0; offset < sizeof(nowret); offset++) {
 | ||||
| //			bus_write(8, dest + offset, *((uint8_t *) &nowret + offset));
 | ||||
| //		}
 | ||||
| //
 | ||||
| //		state->Reg[0] = ret;
 | ||||
| //		return TRUE;
 | ||||
| //		}
 | ||||
| //	
 | ||||
| //	case SWI_Gettimeofday: {
 | ||||
| //		uint32_t dest1 = state->Reg[0];
 | ||||
| //		uint32_t dest2 = state->Reg[1]; // Unsure of this
 | ||||
| //		struct timeval val;
 | ||||
| //		struct timezone zone;
 | ||||
| //		struct target_timeval32 valret;
 | ||||
| //		struct target_timezone32 zoneret;
 | ||||
| //	
 | ||||
| //		uint32_t ret = gettimeofday(&val, &zone);
 | ||||
| //		valret.tv_sec = val.tv_sec;
 | ||||
| //		valret.tv_usec = val.tv_usec;
 | ||||
| //		zoneret.tz_dsttime = zoneret.tz_dsttime;
 | ||||
| //		zoneret.tz_minuteswest = zoneret.tz_minuteswest;
 | ||||
| //
 | ||||
| //		if (ret == -1){
 | ||||
| //			debug("syscall %s error %d\n", "SWI_Gettimeofday", ret);
 | ||||
| //			state->Reg[0] = ret;
 | ||||
| //			return FALSE;
 | ||||
| //		}
 | ||||
| //		
 | ||||
| //		uint32_t offset;
 | ||||
| //		if (dest1) {
 | ||||
| //			for (offset = 0; offset < sizeof(valret); offset++) {
 | ||||
| //				bus_write(8, dest1 + offset, *((uint8_t *) &valret + offset));
 | ||||
| //			}
 | ||||
| //			state->Reg[0] = ret;
 | ||||
| //		}
 | ||||
| //		if (dest2) {
 | ||||
| //			for (offset = 0; offset < sizeof(zoneret); offset++) {
 | ||||
| //				bus_write(8, dest2 + offset, *((uint8_t *) &zoneret + offset));
 | ||||
| //			}
 | ||||
| //			state->Reg[0] = ret;
 | ||||
| //		}
 | ||||
| //
 | ||||
| //		return TRUE;
 | ||||
| //	}
 | ||||
| //	case SWI_Brk:
 | ||||
| //		/* initialize brk value */
 | ||||
| //		/* suppose that brk_static doesn't reach 0xffffffff... */
 | ||||
| //		if (brk_static == -1) {
 | ||||
| //			brk_static = (get_skyeye_pref()->info).brk;
 | ||||
| //		}
 | ||||
| //
 | ||||
| //		/* FIXME there might be a need to do a mmap */
 | ||||
| //		
 | ||||
| //		if(state->Reg[0]){
 | ||||
| //			if (get_skyeye_exec_info()->mmap_access) {
 | ||||
| //				/* if new brk is greater than current brk, allocate memory */
 | ||||
| //				if (state->Reg[0] > brk_static) {
 | ||||
| //					uint32_t ret = mmap( (void *) brk_static, state->Reg[0] - brk_static,
 | ||||
| //							   PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0 );
 | ||||
| //					if (ret != MAP_FAILED)
 | ||||
| //						brk_static = ret;
 | ||||
| //				}
 | ||||
| //			}
 | ||||
| //			brk_static = state->Reg[0];
 | ||||
| //			//state->Reg[0] = 0; /* FIXME return value of brk set to be the address on success */
 | ||||
| //		} else {
 | ||||
| //			state->Reg[0] = brk_static;
 | ||||
| //		}
 | ||||
| //		return TRUE;
 | ||||
| //
 | ||||
| //	case SWI_Break:
 | ||||
| //		state->Emulate = FALSE;
 | ||||
| //		return TRUE;
 | ||||
| //
 | ||||
| //	case SWI_Mmap:{
 | ||||
| //		int addr = state->Reg[0];
 | ||||
| //		int len = state->Reg[1];
 | ||||
| //		int prot = state->Reg[2];
 | ||||
| //		int flag = state->Reg[3];
 | ||||
| //		int fd = state->Reg[4];
 | ||||
| //		int offset = state->Reg[5];
 | ||||
| //		mmap_area_t *area = new_mmap_area(addr, len);
 | ||||
| //		state->Reg[0] = area->bank.addr;
 | ||||
| //		//printf("syscall %d mmap(0x%x,%x,0x%x,0x%x,%d,0x%x) = 0x%x\n",\ | ||||
| //				SWI_Mmap, addr, len, prot, flag, fd, offset, state->Reg[0]);
 | ||||
| //		return TRUE;
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	case SWI_Munmap:
 | ||||
| //		state->Reg[0] = 0;
 | ||||
| //		return TRUE;
 | ||||
| //		
 | ||||
| //	case SWI_Mmap2:{
 | ||||
| //		int addr = state->Reg[0];
 | ||||
| //		int len = state->Reg[1];
 | ||||
| //		int prot = state->Reg[2];
 | ||||
| //		int flag = state->Reg[3];
 | ||||
| //		int fd = state->Reg[4];
 | ||||
| //		int offset = state->Reg[5] * 4096; /* page offset */
 | ||||
| //		mmap_area_t *area = new_mmap_area(addr, len);
 | ||||
| //		state->Reg[0] = area->bank.addr;
 | ||||
| //		
 | ||||
| //		return TRUE;
 | ||||
| //	}
 | ||||
| //
 | ||||
| //	case SWI_Breakpoint:
 | ||||
| //		//chy 2005-09-12 change below line
 | ||||
| //		//state->EndCondition = RDIError_BreakpointReached;
 | ||||
| //		//printf ("SKYEYE: in armos.c : should not come here!!!!\n");
 | ||||
| //		state->EndCondition = 0;
 | ||||
| //		/*modified by ksh to support breakpoiont*/
 | ||||
| //		state->Emulate = STOP;
 | ||||
| //		return (TRUE);
 | ||||
| //	case SWI_Uname:
 | ||||
| //		{
 | ||||
| //		struct utsname *uts = (uintptr_t) state->Reg[0]; /* uname should write data in this address */
 | ||||
| //		struct utsname utsbuf;
 | ||||
| //		//printf("Uname size is %x\n", sizeof(utsbuf));
 | ||||
| //		char *buf;
 | ||||
| //		uintptr_t sp ; /* used as a temporary address */
 | ||||
| //
 | ||||
| //#define COPY_UTS_STRING(addr) 					\ | ||||
| //			buf = addr;				\ | ||||
| //			while(*buf != NULL) { 			\ | ||||
| //				bus_write(8, sp, *buf); 	\ | ||||
| //				sp++; 				\ | ||||
| //				buf++;	 			\ | ||||
| //			}
 | ||||
| //#define COPY_UTS(field)	/*printf("%s: %s at %p\n", #field, utsbuf.field, uts->field);*/	\ | ||||
| //			sp = (uintptr_t) uts->field;						\ | ||||
| //			COPY_UTS_STRING((&utsbuf)->field);
 | ||||
| //
 | ||||
| //		if (uname(&utsbuf) < 0) {
 | ||||
| //			printf("syscall uname: utsname error\n");
 | ||||
| //			state->Reg[0] = -1;
 | ||||
| //			return FALSE;
 | ||||
| //		}
 | ||||
| //		
 | ||||
| //		/* FIXME for now, this is just the host system call
 | ||||
| //		   Some data should be missing, as it depends on
 | ||||
| //		   the version of utsname */
 | ||||
| //		COPY_UTS(sysname);
 | ||||
| //		COPY_UTS(nodename);
 | ||||
| //		COPY_UTS(release);
 | ||||
| //		COPY_UTS(version);
 | ||||
| //		COPY_UTS(machine);
 | ||||
| //		
 | ||||
| //		state->Reg[0] = 0;
 | ||||
| //		return TRUE;
 | ||||
| //		}
 | ||||
| //	case SWI_Fcntl:
 | ||||
| //		{
 | ||||
| //			uint32_t fd = state->Reg[0];
 | ||||
| //			uint32_t cmd = state->Reg[1];
 | ||||
| //			uint32_t arg = state->Reg[2];
 | ||||
| //			uint32_t ret;
 | ||||
| //
 | ||||
| //			switch(cmd){
 | ||||
| //			case (F_GETFD):
 | ||||
| //			{
 | ||||
| //				ret = fcntl(fd, cmd, arg);
 | ||||
| //				//printf("syscall fcntl for getfd not implemented, ret %d\n", ret);
 | ||||
| //				state->Reg[0] = ret;
 | ||||
| //				return FALSE;
 | ||||
| //			}
 | ||||
| //			default:
 | ||||
| //				break;
 | ||||
| //			}
 | ||||
| //
 | ||||
| //			printf("syscall fcntl unimplemented fd %x cmd %x\n", fd, cmd);
 | ||||
| //			state->Reg[0] = -1;
 | ||||
| //			return FALSE;
 | ||||
| //
 | ||||
| //		}
 | ||||
| //	case SWI_Fstat64:
 | ||||
| //		{
 | ||||
| //			uint32_t dest = state->Reg[1];
 | ||||
| //			uint32_t fd = state->Reg[0];
 | ||||
| //			struct stat64 statbuf;
 | ||||
| //			struct target_stat64 statret;
 | ||||
| //			memset(&statret, 0, sizeof(struct target_stat64));
 | ||||
| //			uint32_t ret = fstat64(fd, &statbuf);
 | ||||
| //
 | ||||
| //			if (ret == -1){
 | ||||
| //				printf("syscall %s returned error\n", "SWI_Fstat");
 | ||||
| //				state->Reg[0] = ret;
 | ||||
| //				return FALSE;
 | ||||
| //			}
 | ||||
| //			
 | ||||
| //			/* copy statbuf to the process memory space
 | ||||
| //			   FIXME can't say if endian has an effect here */
 | ||||
| //			uint32_t offset;
 | ||||
| //			//printf("Fstat system is size %x\n", sizeof(statbuf));
 | ||||
| //			//printf("Fstat target is size %x\n", sizeof(statret));
 | ||||
| //			
 | ||||
| //			/* we copy system structure data stat64 into arm fixed size structure target_stat64 */
 | ||||
| //			statret.st_dev = 	statbuf.st_dev;
 | ||||
| //			statret.st_ino = 	statbuf.st_ino;
 | ||||
| //			statret.st_mode = 	statbuf.st_mode;
 | ||||
| //			statret.st_nlink = 	statbuf.st_nlink;
 | ||||
| //			statret.st_uid = 	statbuf.st_uid;
 | ||||
| //			statret.st_gid = 	statbuf.st_gid;
 | ||||
| //			statret.st_rdev = 	statbuf.st_rdev;
 | ||||
| //			statret.st_size = 	statbuf.st_size;
 | ||||
| //			statret.st_blksize = 	statbuf.st_blksize;
 | ||||
| //			statret.st_blocks = 	statbuf.st_blocks;
 | ||||
| //			statret.st32_atime = 	statbuf.st_atime;
 | ||||
| //			statret.st32_mtime = 	statbuf.st_mtime;
 | ||||
| //			statret.st32_ctime = 	statbuf.st_ctime;
 | ||||
| //			
 | ||||
| //			for (offset = 0; offset < sizeof(statret); offset++) {
 | ||||
| //				bus_write(8, dest + offset, *((uint8_t *) &statret + offset));
 | ||||
| //			}
 | ||||
| //
 | ||||
| //			state->Reg[0] = ret;
 | ||||
| //			return TRUE;
 | ||||
| //		}
 | ||||
| //	case SWI_Set_tls:
 | ||||
| //		{
 | ||||
| //			//printf("syscall set_tls unimplemented\n");
 | ||||
| //			state->mmu.thread_uro_id = state->Reg[0];
 | ||||
| //			state->CP15[CP15_THREAD_URO - CP15_BASE] = state->Reg[0];
 | ||||
| //			state->Reg[0] = 0;
 | ||||
| //			return FALSE;
 | ||||
| //		}
 | ||||
| //#if 0
 | ||||
| //	case SWI_Clock:
 | ||||
| //		/* return number of centi-seconds... */
 | ||||
| //		state->Reg[0] =
 | ||||
| //#ifdef CLOCKS_PER_SEC
 | ||||
| //			(CLOCKS_PER_SEC >= 100)
 | ||||
| //			? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
 | ||||
| //			: (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
 | ||||
| //#else
 | ||||
| //			/* presume unix... clock() returns microseconds */
 | ||||
| //			(ARMword) (clock () / 10000);
 | ||||
| //#endif
 | ||||
| //		return (TRUE);
 | ||||
| //
 | ||||
| //	case SWI_Time:
 | ||||
| //		state->Reg[0] = (ARMword) time (NULL);
 | ||||
| //		return (TRUE);
 | ||||
| //	case SWI_Flen:
 | ||||
| //		SWIflen (state, state->Reg[0]);
 | ||||
| //		return (TRUE);
 | ||||
| //
 | ||||
| //#endif
 | ||||
| 	default: | ||||
| 
 | ||||
| 		_dbg_assert_msg_(ARM11, false, "ImplementMe: ARMul_OSHandleSWI!"); | ||||
| 
 | ||||
| 		return (FALSE); | ||||
| 	} | ||||
| } | ||||
| //
 | ||||
| ///**
 | ||||
| // * @brief For mmap syscall.A mmap_area is a memory bank. Get from ppc.
 | ||||
| // */
 | ||||
| //static mmap_area_t* new_mmap_area(int sim_addr, int len){
 | ||||
| //	mmap_area_t *area = (mmap_area_t *)malloc(sizeof(mmap_area_t));
 | ||||
| //	if(area == NULL){
 | ||||
| //		printf("error, failed %s\n",__FUNCTION__);
 | ||||
| //		exit(0);
 | ||||
| //	}
 | ||||
| //#if FAST_MEMORY   
 | ||||
| //	if (mmap_next_base == -1)
 | ||||
| //	{
 | ||||
| //		mmap_next_base = get_skyeye_exec_info()->brk;
 | ||||
| //	}
 | ||||
| //#endif
 | ||||
| //
 | ||||
| //	memset(area, 0x0, sizeof(mmap_area_t));
 | ||||
| //	area->bank.addr = mmap_next_base;
 | ||||
| //	area->bank.len = len;
 | ||||
| //	area->bank.bank_write = mmap_mem_write;
 | ||||
| //	area->bank.bank_read = mmap_mem_read;
 | ||||
| //	area->bank.type = MEMTYPE_RAM;
 | ||||
| //	area->bank.objname = "mmap";
 | ||||
| //	addr_mapping(&area->bank);
 | ||||
| //
 | ||||
| //#if FAST_MEMORY
 | ||||
| //	if (get_skyeye_exec_info()->mmap_access)
 | ||||
| //	{
 | ||||
| //		/* FIXME check proper flags */
 | ||||
| //		/* FIXME we may delete the need of banks up there */
 | ||||
| //		uint32_t ret = mmap(mmap_next_base, len, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 | ||||
| //		mmap_next_base = ret;
 | ||||
| //	}
 | ||||
| //	area->mmap_addr = (uint8_t*)get_dma_addr(mmap_next_base);
 | ||||
| //#else	
 | ||||
| //	area->mmap_addr = malloc(len);
 | ||||
| //	if(area->mmap_addr == NULL){
 | ||||
| //		printf("error mmap malloc\n");
 | ||||
| //		exit(0);
 | ||||
| //	}
 | ||||
| //	memset(area->mmap_addr, 0x0, len);
 | ||||
| //#endif
 | ||||
| //	
 | ||||
| //	area->next = NULL;
 | ||||
| //	if(mmap_global){
 | ||||
| //		area->next = mmap_global->next;
 | ||||
| //		mmap_global->next = area;
 | ||||
| //	}else{
 | ||||
| //		mmap_global = area;
 | ||||
| //	}
 | ||||
| //	mmap_next_base = mmap_next_base + len;
 | ||||
| //	return area;
 | ||||
| //}
 | ||||
| //
 | ||||
| //static mmap_area_t *get_mmap_area(int addr){
 | ||||
| //	mmap_area_t *tmp = mmap_global;
 | ||||
| //	while(tmp){
 | ||||
| //		if ((tmp->bank.addr <= addr) && (tmp->bank.addr + tmp->bank.len > addr)){
 | ||||
| //			return tmp;
 | ||||
| //		}
 | ||||
| //		tmp = tmp->next;
 | ||||
| //	}
 | ||||
| //	printf("cannot get mmap area:addr=0x%x\n", addr);
 | ||||
| //	return NULL;
 | ||||
| //}
 | ||||
| //
 | ||||
| ///**
 | ||||
| // * @brief the mmap_area bank write function. Get from ppc.
 | ||||
| // *
 | ||||
| // * @param size size to write, 8/16/32
 | ||||
| // * @param addr address to write
 | ||||
| // * @param value value to write
 | ||||
| // *
 | ||||
| // * @return sucess return 1,otherwise 0.
 | ||||
| // */
 | ||||
| //static char mmap_mem_write(short size, int addr, uint32_t value){
 | ||||
| //	mmap_area_t *area_tmp = get_mmap_area(addr);
 | ||||
| //	mem_bank_t *bank_tmp = &area_tmp->bank;
 | ||||
| //	int offset = addr - bank_tmp->addr;
 | ||||
| //	switch(size){
 | ||||
| //		case 8:{
 | ||||
| //			//uint8_t value_endian = value;
 | ||||
| //			uint8_t value_endian = (uint8_t)value;
 | ||||
| //			*(uint8_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
 | ||||
| //			debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
 | ||||
| //			break;
 | ||||
| //		}
 | ||||
| //		case 16:{
 | ||||
| //			//uint16_t value_endian = half_to_BE((uint16_t)value);
 | ||||
| //			uint16_t value_endian = ((uint16_t)value);
 | ||||
| //			*(uint16_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
 | ||||
| //			debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
 | ||||
| //			break;
 | ||||
| //		}
 | ||||
| //		case 32:{
 | ||||
| //			//uint32_t value_endian = word_to_BE((uint32_t)value);
 | ||||
| //			uint32_t value_endian = ((uint32_t)value);
 | ||||
| //			*(uint32_t *)&(((char *)area_tmp->mmap_addr)[offset]) = value_endian;
 | ||||
| //			debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,value_endian);
 | ||||
| //			break;
 | ||||
| //		}
 | ||||
| //		default:
 | ||||
| //			printf("invalid size %d\n",size);
 | ||||
| //			return 0;
 | ||||
| //	}
 | ||||
| //	return 1;
 | ||||
| //}
 | ||||
| //
 | ||||
| ///**
 | ||||
| // * @brief the mmap_area bank read function. Get from ppc.
 | ||||
| // *
 | ||||
| // * @param size size to read, 8/16/32
 | ||||
| // * @param addr address to read
 | ||||
| // * @param value value to read
 | ||||
| // *
 | ||||
| // * @return sucess return 1,otherwise 0.
 | ||||
| // */
 | ||||
| //static char mmap_mem_read(short size, int addr, uint32_t * value){
 | ||||
| //	mmap_area_t *area_tmp = get_mmap_area(addr);
 | ||||
| //	mem_bank_t *bank_tmp = &area_tmp->bank;
 | ||||
| //	int offset = addr - bank_tmp->addr;
 | ||||
| //	switch(size){
 | ||||
| //		case 8:{
 | ||||
| //			//*(uint8_t *)value = *(uint8_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]);
 | ||||
| //			*value = *(uint8_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]);
 | ||||
| //			debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint32_t*)value);
 | ||||
| //			break;
 | ||||
| //		}
 | ||||
| //		case 16:{
 | ||||
| //			//*(uint16_t *)value = half_from_BE(*(uint16_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
 | ||||
| //			*value = (*(uint16_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
 | ||||
| //			debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint16_t*)value);
 | ||||
| //			break;
 | ||||
| //		}
 | ||||
| //		case 32:
 | ||||
| //			//*value = (uint32_t)word_from_BE(*(uint32_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
 | ||||
| //			*value = (uint32_t)(*(uint32_t *)&(((uint8_t *)area_tmp->mmap_addr)[offset]));
 | ||||
| //			debug("in %s,size=%d,addr=0x%x,value=0x%x\n",__FUNCTION__,size,addr,*(uint32_t*)value);
 | ||||
| //			break;
 | ||||
| //		default:
 | ||||
| //			printf("invalid size %d\n",size);
 | ||||
| //			return 0;
 | ||||
| //	}
 | ||||
| //	return 1;
 | ||||
| //}
 | ||||
							
								
								
									
										953
									
								
								src/core/src/arm/armsupp.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										953
									
								
								src/core/src/arm/armsupp.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,953 @@ | |||
| /*  armsupp.c -- ARMulator support code:  ARM6 Instruction Emulator.
 | ||||
|     Copyright (C) 1994 Advanced RISC Machines Ltd. | ||||
|   | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
|   | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|   | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||||
| 
 | ||||
| #include "armdefs.h" | ||||
| #include "armemu.h" | ||||
| //#include "ansidecl.h"
 | ||||
| #include "skyeye_defs.h" | ||||
| unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, | ||||
|                                         unsigned cpnum); | ||||
| //extern int skyeye_instr_debug;
 | ||||
| /* Definitions for the support routines.  */ | ||||
| 
 | ||||
| static ARMword ModeToBank (ARMword); | ||||
| static void EnvokeList (ARMul_State *, unsigned int, unsigned int); | ||||
| 
 | ||||
| struct EventNode | ||||
| {				/* An event list node.  */ | ||||
| 	unsigned (*func) (ARMul_State *);	/* The function to call.  */ | ||||
| 	struct EventNode *next; | ||||
| }; | ||||
| 
 | ||||
| /* This routine returns the value of a register from a mode.  */ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg) | ||||
| { | ||||
| 	mode &= MODEBITS; | ||||
| 	if (mode != state->Mode) | ||||
| 		return (state->RegBank[ModeToBank ((ARMword) mode)][reg]); | ||||
| 	else | ||||
| 		return (state->Reg[reg]); | ||||
| } | ||||
| 
 | ||||
| /* This routine sets the value of a register for a mode.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value) | ||||
| { | ||||
| 	mode &= MODEBITS; | ||||
| 	if (mode != state->Mode) | ||||
| 		state->RegBank[ModeToBank ((ARMword) mode)][reg] = value; | ||||
| 	else | ||||
| 		state->Reg[reg] = value; | ||||
| } | ||||
| 
 | ||||
| /* This routine returns the value of the PC, mode independently.  */ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_GetPC (ARMul_State * state) | ||||
| { | ||||
| 	if (state->Mode > SVC26MODE) | ||||
| 		return state->Reg[15]; | ||||
| 	else | ||||
| 		return R15PC; | ||||
| } | ||||
| 
 | ||||
| /* This routine returns the value of the PC, mode independently.  */ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_GetNextPC (ARMul_State * state) | ||||
| { | ||||
| 	if (state->Mode > SVC26MODE) | ||||
| 		return state->Reg[15] + isize; | ||||
| 	else | ||||
| 		return (state->Reg[15] + isize) & R15PCBITS; | ||||
| } | ||||
| 
 | ||||
| /* This routine sets the value of the PC.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_SetPC (ARMul_State * state, ARMword value) | ||||
| { | ||||
| 	if (ARMul_MODE32BIT) | ||||
| 		state->Reg[15] = value & PCBITS; | ||||
| 	else | ||||
| 		state->Reg[15] = R15CCINTMODE | (value & R15PCBITS); | ||||
| 	FLUSHPIPE; | ||||
| } | ||||
| 
 | ||||
| /* This routine returns the value of register 15, mode independently.  */ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_GetR15 (ARMul_State * state) | ||||
| { | ||||
| 	if (state->Mode > SVC26MODE) | ||||
| 		return (state->Reg[15]); | ||||
| 	else | ||||
| 		return (R15PC | ECC | ER15INT | EMODE); | ||||
| } | ||||
| 
 | ||||
| /* This routine sets the value of Register 15.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_SetR15 (ARMul_State * state, ARMword value) | ||||
| { | ||||
| 	if (ARMul_MODE32BIT) | ||||
| 		state->Reg[15] = value & PCBITS; | ||||
| 	else { | ||||
| 		state->Reg[15] = value; | ||||
| 		ARMul_R15Altered (state); | ||||
| 	} | ||||
| 	FLUSHPIPE; | ||||
| } | ||||
| 
 | ||||
| /* This routine returns the value of the CPSR.  */ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_GetCPSR (ARMul_State * state) | ||||
| { | ||||
| 	//chy 2003-08-20: below is from gdb20030716, maybe isn't suitable for system simulator
 | ||||
| 	//return (CPSR | state->Cpsr); for gdb20030716
 | ||||
| 	return (CPSR);		//had be tested in old skyeye with gdb5.0-5.3
 | ||||
| } | ||||
| 
 | ||||
| /* This routine sets the value of the CPSR.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_SetCPSR (ARMul_State * state, ARMword value) | ||||
| { | ||||
| 	state->Cpsr = value; | ||||
| 	ARMul_CPSRAltered (state); | ||||
| } | ||||
| 
 | ||||
| /* This routine does all the nasty bits involved in a write to the CPSR,
 | ||||
|    including updating the register bank, given a MSR instruction.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs) | ||||
| { | ||||
| 	state->Cpsr = ARMul_GetCPSR (state); | ||||
| 	//chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
 | ||||
| 	if (state->Mode != USER26MODE && state->Mode != USER32MODE ) { | ||||
| 		/* In user mode, only write flags.  */ | ||||
| 		if (BIT (16)) | ||||
| 			SETPSR_C (state->Cpsr, rhs); | ||||
| 		if (BIT (17)) | ||||
| 			SETPSR_X (state->Cpsr, rhs); | ||||
| 		if (BIT (18)) | ||||
| 			SETPSR_S (state->Cpsr, rhs); | ||||
| 	} | ||||
| 	if (BIT (19)) | ||||
| 		SETPSR_F (state->Cpsr, rhs); | ||||
| 	ARMul_CPSRAltered (state); | ||||
| } | ||||
| 
 | ||||
| /* Get an SPSR from the specified mode.  */ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_GetSPSR (ARMul_State * state, ARMword mode) | ||||
| { | ||||
| 	ARMword bank = ModeToBank (mode & MODEBITS); | ||||
| 
 | ||||
| 	if (!BANK_CAN_ACCESS_SPSR (bank)) | ||||
| 		return ARMul_GetCPSR (state); | ||||
| 
 | ||||
| 	return state->Spsr[bank]; | ||||
| } | ||||
| 
 | ||||
| /* This routine does a write to an SPSR.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) | ||||
| { | ||||
| 	ARMword bank = ModeToBank (mode & MODEBITS); | ||||
| 
 | ||||
| 	if (BANK_CAN_ACCESS_SPSR (bank)) | ||||
| 		state->Spsr[bank] = value; | ||||
| } | ||||
| 
 | ||||
| /* This routine does a write to the current SPSR, given an MSR instruction.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs) | ||||
| { | ||||
| 	if (BANK_CAN_ACCESS_SPSR (state->Bank)) { | ||||
| 		if (BIT (16)) | ||||
| 			SETPSR_C (state->Spsr[state->Bank], rhs); | ||||
| 		if (BIT (17)) | ||||
| 			SETPSR_X (state->Spsr[state->Bank], rhs); | ||||
| 		if (BIT (18)) | ||||
| 			SETPSR_S (state->Spsr[state->Bank], rhs); | ||||
| 		if (BIT (19)) | ||||
| 			SETPSR_F (state->Spsr[state->Bank], rhs); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* This routine updates the state of the emulator after the Cpsr has been
 | ||||
|    changed.  Both the processor flags and register bank are updated.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_CPSRAltered (ARMul_State * state) | ||||
| { | ||||
| 	ARMword oldmode; | ||||
| 
 | ||||
| 	if (state->prog32Sig == LOW) | ||||
| 		state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS); | ||||
| 
 | ||||
| 	oldmode = state->Mode; | ||||
| 
 | ||||
| 	if (state->Mode != (state->Cpsr & MODEBITS)) { | ||||
| 		state->Mode = | ||||
| 			ARMul_SwitchMode (state, state->Mode, | ||||
| 					  state->Cpsr & MODEBITS); | ||||
| 
 | ||||
| 		state->NtransSig = (state->Mode & 3) ? HIGH : LOW; | ||||
| 	} | ||||
| 	//state->Cpsr &= ~MODEBITS;
 | ||||
| 
 | ||||
| 	ASSIGNINT (state->Cpsr & INTBITS); | ||||
| 	//state->Cpsr &= ~INTBITS;
 | ||||
| 	ASSIGNN ((state->Cpsr & NBIT) != 0); | ||||
| 	//state->Cpsr &= ~NBIT;
 | ||||
| 	ASSIGNZ ((state->Cpsr & ZBIT) != 0); | ||||
| 	//state->Cpsr &= ~ZBIT;
 | ||||
| 	ASSIGNC ((state->Cpsr & CBIT) != 0); | ||||
| 	//state->Cpsr &= ~CBIT;
 | ||||
| 	ASSIGNV ((state->Cpsr & VBIT) != 0); | ||||
| 	//state->Cpsr &= ~VBIT;
 | ||||
| 	ASSIGNS ((state->Cpsr & SBIT) != 0); | ||||
| 	//state->Cpsr &= ~SBIT;
 | ||||
| #ifdef MODET | ||||
| 	ASSIGNT ((state->Cpsr & TBIT) != 0); | ||||
| 	//state->Cpsr &= ~TBIT;
 | ||||
| #endif | ||||
| 
 | ||||
| 	if (oldmode > SVC26MODE) { | ||||
| 		if (state->Mode <= SVC26MODE) { | ||||
| 			state->Emulate = CHANGEMODE; | ||||
| 			state->Reg[15] = ECC | ER15INT | EMODE | R15PC; | ||||
| 		} | ||||
| 	} | ||||
| 	else { | ||||
| 		if (state->Mode > SVC26MODE) { | ||||
| 			state->Emulate = CHANGEMODE; | ||||
| 			state->Reg[15] = R15PC; | ||||
| 		} | ||||
| 		else | ||||
| 			state->Reg[15] = ECC | ER15INT | EMODE | R15PC; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* This routine updates the state of the emulator after register 15 has
 | ||||
|    been changed.  Both the processor flags and register bank are updated. | ||||
|    This routine should only be called from a 26 bit mode.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_R15Altered (ARMul_State * state) | ||||
| { | ||||
| 	if (state->Mode != R15MODE) { | ||||
| 		state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE); | ||||
| 		state->NtransSig = (state->Mode & 3) ? HIGH : LOW; | ||||
| 	} | ||||
| 
 | ||||
| 	if (state->Mode > SVC26MODE) | ||||
| 		state->Emulate = CHANGEMODE; | ||||
| 
 | ||||
| 	ASSIGNR15INT (R15INT); | ||||
| 
 | ||||
| 	ASSIGNN ((state->Reg[15] & NBIT) != 0); | ||||
| 	ASSIGNZ ((state->Reg[15] & ZBIT) != 0); | ||||
| 	ASSIGNC ((state->Reg[15] & CBIT) != 0); | ||||
| 	ASSIGNV ((state->Reg[15] & VBIT) != 0); | ||||
| } | ||||
| 
 | ||||
| /* This routine controls the saving and restoring of registers across mode
 | ||||
|    changes.  The regbank matrix is largely unused, only rows 13 and 14 are | ||||
|    used across all modes, 8 to 14 are used for FIQ, all others use the USER | ||||
|    column.  It's easier this way.  old and new parameter are modes numbers. | ||||
|    Notice the side effect of changing the Bank variable.  */ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) | ||||
| { | ||||
| 	unsigned i; | ||||
| 	ARMword oldbank; | ||||
| 	ARMword newbank; | ||||
| 	static int revision_value = 53; | ||||
| 
 | ||||
| 	oldbank = ModeToBank (oldmode); | ||||
| 	newbank = state->Bank = ModeToBank (newmode); | ||||
| 
 | ||||
| 	/* Do we really need to do it?  */ | ||||
| 	if (oldbank != newbank) { | ||||
| 		if (oldbank == 3 && newbank == 2) { | ||||
| 			//printf("icounter is %d PC is %x MODE CHANGED : %d --> %d\n", state->NumInstrs, state->pc, oldbank, newbank);
 | ||||
| 			if (state->NumInstrs >= 5832487) { | ||||
| //				printf("%d, ", state->NumInstrs + revision_value);
 | ||||
| //				printf("revision_value : %d\n", revision_value);
 | ||||
| 				revision_value ++; | ||||
| 			} | ||||
| 		} | ||||
| 		/* Save away the old registers.  */ | ||||
| 		switch (oldbank) { | ||||
| 		case USERBANK: | ||||
| 		case IRQBANK: | ||||
| 		case SVCBANK: | ||||
| 		case ABORTBANK: | ||||
| 		case UNDEFBANK: | ||||
| 			if (newbank == FIQBANK) | ||||
| 				for (i = 8; i < 13; i++) | ||||
| 					state->RegBank[USERBANK][i] = | ||||
| 						state->Reg[i]; | ||||
| 			state->RegBank[oldbank][13] = state->Reg[13]; | ||||
| 			state->RegBank[oldbank][14] = state->Reg[14]; | ||||
| 			break; | ||||
| 		case FIQBANK: | ||||
| 			for (i = 8; i < 15; i++) | ||||
| 				state->RegBank[FIQBANK][i] = state->Reg[i]; | ||||
| 			break; | ||||
| 		case DUMMYBANK: | ||||
| 			for (i = 8; i < 15; i++) | ||||
| 				state->RegBank[DUMMYBANK][i] = 0; | ||||
| 			break; | ||||
| 		default: | ||||
| 			abort (); | ||||
| 		} | ||||
| 
 | ||||
| 		/* Restore the new registers.  */ | ||||
| 		switch (newbank) { | ||||
| 		case USERBANK: | ||||
| 		case IRQBANK: | ||||
| 		case SVCBANK: | ||||
| 		case ABORTBANK: | ||||
| 		case UNDEFBANK: | ||||
| 			if (oldbank == FIQBANK) | ||||
| 				for (i = 8; i < 13; i++) | ||||
| 					state->Reg[i] = | ||||
| 						state->RegBank[USERBANK][i]; | ||||
| 			state->Reg[13] = state->RegBank[newbank][13]; | ||||
| 			state->Reg[14] = state->RegBank[newbank][14]; | ||||
| 			break; | ||||
| 		case FIQBANK: | ||||
| 			for (i = 8; i < 15; i++) | ||||
| 				state->Reg[i] = state->RegBank[FIQBANK][i]; | ||||
| 			break; | ||||
| 		case DUMMYBANK: | ||||
| 			for (i = 8; i < 15; i++) | ||||
| 				state->Reg[i] = 0; | ||||
| 			break; | ||||
| 		default: | ||||
| 			abort (); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return newmode; | ||||
| } | ||||
| 
 | ||||
| /* Given a processor mode, this routine returns the
 | ||||
|    register bank that will be accessed in that mode.  */ | ||||
| 
 | ||||
| static ARMword | ||||
| ModeToBank (ARMword mode) | ||||
| { | ||||
| 	static ARMword bankofmode[] = { | ||||
| 		USERBANK, FIQBANK, IRQBANK, SVCBANK, | ||||
| 		DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, | ||||
| 		DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, | ||||
| 		DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, | ||||
| 		USERBANK, FIQBANK, IRQBANK, SVCBANK, | ||||
| 		DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK, | ||||
| 		DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK, | ||||
| 		DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK | ||||
| 	}; | ||||
| 
 | ||||
| 	if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0]))) | ||||
| 		return DUMMYBANK; | ||||
| 
 | ||||
| 	return bankofmode[mode]; | ||||
| } | ||||
| 
 | ||||
| /* Returns the register number of the nth register in a reg list.  */ | ||||
| 
 | ||||
| unsigned | ||||
| ARMul_NthReg (ARMword instr, unsigned number) | ||||
| { | ||||
| 	unsigned bit, upto; | ||||
| 
 | ||||
| 	for (bit = 0, upto = 0; upto <= number; bit++) | ||||
| 		if (BIT (bit)) | ||||
| 			upto++; | ||||
| 
 | ||||
| 	return (bit - 1); | ||||
| } | ||||
| 
 | ||||
| /* Assigns the N and Z flags depending on the value of result.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_NegZero (ARMul_State * state, ARMword result) | ||||
| { | ||||
| 	if (NEG (result)) { | ||||
| 		SETN; | ||||
| 		CLEARZ; | ||||
| 	} | ||||
| 	else if (result == 0) { | ||||
| 		CLEARN; | ||||
| 		SETZ; | ||||
| 	} | ||||
| 	else { | ||||
| 		CLEARN; | ||||
| 		CLEARZ; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* Compute whether an addition of A and B, giving RESULT, overflowed.  */ | ||||
| 
 | ||||
| int | ||||
| AddOverflow (ARMword a, ARMword b, ARMword result) | ||||
| { | ||||
| 	return ((NEG (a) && NEG (b) && POS (result)) | ||||
| 		|| (POS (a) && POS (b) && NEG (result))); | ||||
| } | ||||
| 
 | ||||
| /* Compute whether a subtraction of A and B, giving RESULT, overflowed.  */ | ||||
| 
 | ||||
| int | ||||
| SubOverflow (ARMword a, ARMword b, ARMword result) | ||||
| { | ||||
| 	return ((NEG (a) && POS (b) && POS (result)) | ||||
| 		|| (POS (a) && NEG (b) && NEG (result))); | ||||
| } | ||||
| 
 | ||||
| /* Assigns the C flag after an addition of a and b to give result.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||||
| { | ||||
| 	ASSIGNC ((NEG (a) && NEG (b)) || | ||||
| 		 (NEG (a) && POS (result)) || (NEG (b) && POS (result))); | ||||
| } | ||||
| 
 | ||||
| /* Assigns the V flag after an addition of a and b to give result.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||||
| { | ||||
| 	ASSIGNV (AddOverflow (a, b, result)); | ||||
| } | ||||
| 
 | ||||
| /* Assigns the C flag after an subtraction of a and b to give result.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||||
| { | ||||
| 	ASSIGNC ((NEG (a) && POS (b)) || | ||||
| 		 (NEG (a) && POS (result)) || (POS (b) && POS (result))); | ||||
| } | ||||
| 
 | ||||
| /* Assigns the V flag after an subtraction of a and b to give result.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||||
| { | ||||
| 	ASSIGNV (SubOverflow (a, b, result)); | ||||
| } | ||||
| 
 | ||||
| /* This function does the work of generating the addresses used in an
 | ||||
|    LDC instruction.  The code here is always post-indexed, it's up to the | ||||
|    caller to get the input address correct and to handle base register | ||||
|    modification. It also handles the Busy-Waiting.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address) | ||||
| { | ||||
| 	unsigned cpab; | ||||
| 	ARMword data; | ||||
| 
 | ||||
| 	UNDEF_LSCPCBaseWb; | ||||
| 	//printf("SKYEYE ARMul_LDC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
 | ||||
| /*chy 2004-05-23 should update this function in the future,should concern dataabort*/ | ||||
| // chy 2004-05-25 , fix it now,so needn't printf 
 | ||||
| //  printf("SKYEYE ARMul_LDC, should update this function!!!!!\n");
 | ||||
| 	//exit(-1);
 | ||||
| 
 | ||||
| 	if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||||
| 		/* 
 | ||||
| 		   printf | ||||
| 		   ("SKYEYE ARMul_LDC,NOT ALLOW, underinstr, CPnum is %x, instr %x, addr %x\n", | ||||
| 		   CPNum, instr, address); | ||||
| 		 */ | ||||
| 		ARMul_UndefInstr (state, instr); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ADDREXCEPT (address)) | ||||
| 		INTERNALABORT (address); | ||||
| 
 | ||||
| 	cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0); | ||||
| 	while (cpab == ARMul_BUSY) { | ||||
| 		ARMul_Icycles (state, 1, 0); | ||||
| 
 | ||||
| 		if (IntPending (state)) { | ||||
| 			cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, | ||||
| 						    instr, 0); | ||||
| 			return; | ||||
| 		} | ||||
| 		else | ||||
| 			cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, | ||||
| 						    0); | ||||
| 	} | ||||
| 	if (cpab == ARMul_CANT) { | ||||
| 		/* 
 | ||||
| 		   printf | ||||
| 		   ("SKYEYE ARMul_LDC,NOT CAN, underinstr, CPnum is %x, instr %x, addr %x\n", | ||||
| 		   CPNum, instr, address); | ||||
| 		 */ | ||||
| 		CPTAKEABORT; | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0); | ||||
| 	data = ARMul_LoadWordN (state, address); | ||||
| 	//chy 2004-05-25      
 | ||||
| 	if (state->abortSig || state->Aborted) | ||||
| 		goto L_ldc_takeabort; | ||||
| 
 | ||||
| 	BUSUSEDINCPCN; | ||||
| //chy 2004-05-25
 | ||||
| /*
 | ||||
|   if (BIT (21)) | ||||
|     LSBase = state->Base; | ||||
| */ | ||||
| 
 | ||||
| 	cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); | ||||
| 
 | ||||
| 	while (cpab == ARMul_INC) { | ||||
| 		address += 4; | ||||
| 		data = ARMul_LoadWordN (state, address); | ||||
| 		//chy 2004-05-25  
 | ||||
| 		if (state->abortSig || state->Aborted) | ||||
| 			goto L_ldc_takeabort; | ||||
| 
 | ||||
| 		cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); | ||||
| 	} | ||||
| 
 | ||||
| //chy 2004-05-25
 | ||||
|       L_ldc_takeabort: | ||||
| 	if (BIT (21)) { | ||||
| 		if (! | ||||
| 		    ((state->abortSig || state->Aborted) | ||||
| 		     && state->lateabtSig == LOW)) | ||||
| 			LSBase = state->Base; | ||||
| 	} | ||||
| 
 | ||||
| 	if (state->abortSig || state->Aborted) | ||||
| 		TAKEABORT; | ||||
| } | ||||
| 
 | ||||
| /* This function does the work of generating the addresses used in an
 | ||||
|    STC instruction.  The code here is always post-indexed, it's up to the | ||||
|    caller to get the input address correct and to handle base register | ||||
|    modification. It also handles the Busy-Waiting.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_STC (ARMul_State * state, ARMword instr, ARMword address) | ||||
| { | ||||
| 	unsigned cpab; | ||||
| 	ARMword data; | ||||
| 
 | ||||
| 	UNDEF_LSCPCBaseWb; | ||||
| 
 | ||||
| 	//printf("SKYEYE ARMul_STC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
 | ||||
| 	/*chy 2004-05-23 should update this function in the future,should concern dataabort */ | ||||
| //  skyeye_instr_debug=0;printf("SKYEYE  debug end!!!!\n");
 | ||||
| // chy 2004-05-25 , fix it now,so needn't printf 
 | ||||
| //  printf("SKYEYE ARMul_STC, should update this function!!!!!\n");
 | ||||
| 
 | ||||
| 	//exit(-1);
 | ||||
| 	if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||||
| 		/* 
 | ||||
| 		   printf | ||||
| 		   ("SKYEYE ARMul_STC,NOT ALLOW, undefinstr,  CPnum is %x, instr %x, addr %x\n", | ||||
| 		   CPNum, instr, address); | ||||
| 		 */ | ||||
| 		ARMul_UndefInstr (state, instr); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (ADDREXCEPT (address) || VECTORACCESS (address)) | ||||
| 		INTERNALABORT (address); | ||||
| 
 | ||||
| 	cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data); | ||||
| 	while (cpab == ARMul_BUSY) { | ||||
| 		ARMul_Icycles (state, 1, 0); | ||||
| 		if (IntPending (state)) { | ||||
| 			cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, | ||||
| 						    instr, 0); | ||||
| 			return; | ||||
| 		} | ||||
| 		else | ||||
| 			cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, | ||||
| 						    &data); | ||||
| 	} | ||||
| 
 | ||||
| 	if (cpab == ARMul_CANT) { | ||||
| 		/* 
 | ||||
| 		   printf | ||||
| 		   ("SKYEYE ARMul_STC,CANT, undefinstr,  CPnum is %x, instr %x, addr %x\n", | ||||
| 		   CPNum, instr, address); | ||||
| 		 */ | ||||
| 		CPTAKEABORT; | ||||
| 		return; | ||||
| 	} | ||||
| #ifndef MODE32 | ||||
| 	if (ADDREXCEPT (address) || VECTORACCESS (address)) | ||||
| 		INTERNALABORT (address); | ||||
| #endif | ||||
| 	BUSUSEDINCPCN; | ||||
| //chy 2004-05-25
 | ||||
| /*
 | ||||
|   if (BIT (21)) | ||||
|     LSBase = state->Base; | ||||
| */ | ||||
| 	cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); | ||||
| 	ARMul_StoreWordN (state, address, data); | ||||
| 	//chy 2004-05-25      
 | ||||
| 	if (state->abortSig || state->Aborted) | ||||
| 		goto L_stc_takeabort; | ||||
| 
 | ||||
| 	while (cpab == ARMul_INC) { | ||||
| 		address += 4; | ||||
| 		cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); | ||||
| 		ARMul_StoreWordN (state, address, data); | ||||
| 		//chy 2004-05-25  
 | ||||
| 		if (state->abortSig || state->Aborted) | ||||
| 			goto L_stc_takeabort; | ||||
| 	} | ||||
| //chy 2004-05-25
 | ||||
|       L_stc_takeabort: | ||||
| 	if (BIT (21)) { | ||||
| 		if (! | ||||
| 		    ((state->abortSig || state->Aborted) | ||||
| 		     && state->lateabtSig == LOW)) | ||||
| 			LSBase = state->Base; | ||||
| 	} | ||||
| 
 | ||||
| 	if (state->abortSig || state->Aborted) | ||||
| 		TAKEABORT; | ||||
| } | ||||
| 
 | ||||
| /* This function does the Busy-Waiting for an MCR instruction.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) | ||||
| { | ||||
| 	unsigned cpab; | ||||
| 
 | ||||
| 	//printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source);
 | ||||
| 	if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||||
| 		//chy 2004-07-19 should fix in the future ????!!!!
 | ||||
| 		//printf("SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr  CPnum is %x, source %x\n",CPNum, source);
 | ||||
| 		ARMul_UndefInstr (state, instr); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source); | ||||
| 
 | ||||
| 	while (cpab == ARMul_BUSY) { | ||||
| 		ARMul_Icycles (state, 1, 0); | ||||
| 
 | ||||
| 		if (IntPending (state)) { | ||||
| 			cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, | ||||
| 						    instr, 0); | ||||
| 			return; | ||||
| 		} | ||||
| 		else | ||||
| 			cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, | ||||
| 						    source); | ||||
| 	} | ||||
| 
 | ||||
| 	if (cpab == ARMul_CANT) { | ||||
| 		printf ("SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x\n", instr, CPNum, source); | ||||
| 		ARMul_Abort (state, ARMul_UndefinedInstrV); | ||||
| 	} | ||||
| 	else { | ||||
| 		BUSUSEDINCPCN; | ||||
| 		ARMul_Ccycles (state, 1, 0); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* This function does the Busy-Waiting for an MCRR instruction.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_MCRR (ARMul_State * state, ARMword instr, ARMword source1, ARMword source2) | ||||
| { | ||||
| 	unsigned cpab; | ||||
| 
 | ||||
| 	if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||||
| 		ARMul_UndefInstr (state, instr); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	cpab = (state->MCRR[CPNum]) (state, ARMul_FIRST, instr, source1, source2); | ||||
| 
 | ||||
| 	while (cpab == ARMul_BUSY) { | ||||
| 		ARMul_Icycles (state, 1, 0); | ||||
| 
 | ||||
| 		if (IntPending (state)) { | ||||
| 			cpab = (state->MCRR[CPNum]) (state, ARMul_INTERRUPT, | ||||
| 						    instr, 0, 0); | ||||
| 			return; | ||||
| 		} | ||||
| 		else | ||||
| 			cpab = (state->MCRR[CPNum]) (state, ARMul_BUSY, instr, | ||||
| 						    source1, source2); | ||||
| 	} | ||||
| 	if (cpab == ARMul_CANT) { | ||||
| 		printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x, source %x %x\n", __FUNCTION__, CPNum, instr, source1, source2); | ||||
| 		ARMul_Abort (state, ARMul_UndefinedInstrV); | ||||
| 	} | ||||
| 	else { | ||||
| 		BUSUSEDINCPCN; | ||||
| 		ARMul_Ccycles (state, 1, 0); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* This function does the Busy-Waiting for an MRC instruction.  */ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_MRC (ARMul_State * state, ARMword instr) | ||||
| { | ||||
| 	unsigned cpab; | ||||
| 	ARMword result = 0; | ||||
| 
 | ||||
| 	//printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
 | ||||
| 	if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||||
| 		//chy 2004-07-19 should fix in the future????!!!!
 | ||||
| 		//printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr  CPnum is %x, instr %x\n",CPNum, instr);
 | ||||
| 		ARMul_UndefInstr (state, instr); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result); | ||||
| 	while (cpab == ARMul_BUSY) { | ||||
| 		ARMul_Icycles (state, 1, 0); | ||||
| 		if (IntPending (state)) { | ||||
| 			cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, | ||||
| 						    instr, 0); | ||||
| 			return (0); | ||||
| 		} | ||||
| 		else | ||||
| 			cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, | ||||
| 						    &result); | ||||
| 	} | ||||
| 	if (cpab == ARMul_CANT) { | ||||
| 		printf ("SKYEYE ARMul_MRC,CANT UndefInstr  CPnum is %x, instr %x\n", CPNum, instr); | ||||
| 		ARMul_Abort (state, ARMul_UndefinedInstrV); | ||||
| 		/* Parent will destroy the flags otherwise.  */ | ||||
| 		result = ECC; | ||||
| 	} | ||||
| 	else { | ||||
| 		BUSUSEDINCPCN; | ||||
| 		ARMul_Ccycles (state, 1, 0); | ||||
| 		ARMul_Icycles (state, 1, 0); | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| /* This function does the Busy-Waiting for an MRRC instruction. (to verify) */ | ||||
| 
 | ||||
| void | ||||
| ARMul_MRRC (ARMul_State * state, ARMword instr, ARMword * dest1, ARMword * dest2) | ||||
| { | ||||
| 	unsigned cpab; | ||||
| 	ARMword result1 = 0; | ||||
| 	ARMword result2 = 0; | ||||
| 
 | ||||
| 	if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||||
| 		ARMul_UndefInstr (state, instr); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	cpab = (state->MRRC[CPNum]) (state, ARMul_FIRST, instr, &result1, &result2); | ||||
| 	while (cpab == ARMul_BUSY) { | ||||
| 		ARMul_Icycles (state, 1, 0); | ||||
| 		if (IntPending (state)) { | ||||
| 			cpab = (state->MRRC[CPNum]) (state, ARMul_INTERRUPT, | ||||
| 						    instr, 0, 0); | ||||
| 			return; | ||||
| 		} | ||||
| 		else | ||||
| 			cpab = (state->MRRC[CPNum]) (state, ARMul_BUSY, instr, | ||||
| 						    &result1, &result2); | ||||
| 	} | ||||
| 	if (cpab == ARMul_CANT) { | ||||
| 		printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x\n", __FUNCTION__, CPNum, instr); | ||||
| 		ARMul_Abort (state, ARMul_UndefinedInstrV); | ||||
| 	} | ||||
| 	else { | ||||
| 		BUSUSEDINCPCN; | ||||
| 		ARMul_Ccycles (state, 1, 0); | ||||
| 		ARMul_Icycles (state, 1, 0); | ||||
| 	} | ||||
| 	 | ||||
| 	*dest1 = result1; | ||||
| 	*dest2 = result2; | ||||
| } | ||||
| 
 | ||||
| /* This function does the Busy-Waiting for an CDP instruction.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_CDP (ARMul_State * state, ARMword instr) | ||||
| { | ||||
| 	unsigned cpab; | ||||
| 
 | ||||
| 	if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||||
| 		ARMul_UndefInstr (state, instr); | ||||
| 		return; | ||||
| 	} | ||||
| 	cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr); | ||||
| 	while (cpab == ARMul_BUSY) { | ||||
| 		ARMul_Icycles (state, 1, 0); | ||||
| 		if (IntPending (state)) { | ||||
| 			cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, | ||||
| 						    instr); | ||||
| 			return; | ||||
| 		} | ||||
| 		else | ||||
| 			cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr); | ||||
| 	} | ||||
| 	if (cpab == ARMul_CANT) | ||||
| 		ARMul_Abort (state, ARMul_UndefinedInstrV); | ||||
| 	else | ||||
| 		BUSUSEDN; | ||||
| } | ||||
| 
 | ||||
| /* This function handles Undefined instructions, as CP isntruction.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_UndefInstr (ARMul_State * state, ARMword instr) | ||||
| { | ||||
| 	ERROR_LOG(ARM11, "Undefined instruction!! Instr: 0x%x", instr); | ||||
| 	ARMul_Abort (state, ARMul_UndefinedInstrV); | ||||
| } | ||||
| 
 | ||||
| /* Return TRUE if an interrupt is pending, FALSE otherwise.  */ | ||||
| 
 | ||||
| unsigned | ||||
| IntPending (ARMul_State * state) | ||||
| { | ||||
| 	/* Any exceptions.  */ | ||||
| 	if (state->NresetSig == LOW) { | ||||
| 		ARMul_Abort (state, ARMul_ResetV); | ||||
| 		return TRUE; | ||||
| 	} | ||||
| 	else if (!state->NfiqSig && !FFLAG) { | ||||
| 		ARMul_Abort (state, ARMul_FIQV); | ||||
| 		return TRUE; | ||||
| 	} | ||||
| 	else if (!state->NirqSig && !IFLAG) { | ||||
| 		ARMul_Abort (state, ARMul_IRQV); | ||||
| 		return TRUE; | ||||
| 	} | ||||
| 
 | ||||
| 	return FALSE; | ||||
| } | ||||
| 
 | ||||
| /* Align a word access to a non word boundary.  */ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_Align (ARMul_State *state, ARMword address, ARMword data) | ||||
| { | ||||
| 	/* This code assumes the address is really unaligned,
 | ||||
| 	   as a shift by 32 is undefined in C.  */ | ||||
| 
 | ||||
| 	address = (address & 3) << 3;	/* Get the word address.  */ | ||||
| 	return ((data >> address) | (data << (32 - address)));	/* rot right */ | ||||
| } | ||||
| 
 | ||||
| /* This routine is used to call another routine after a certain number of
 | ||||
|    cycles have been executed. The first parameter is the number of cycles | ||||
|    delay before the function is called, the second argument is a pointer | ||||
|    to the function. A delay of zero doesn't work, just call the function.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_ScheduleEvent (ARMul_State * state, unsigned int delay, | ||||
| 		     unsigned (*what) (ARMul_State *)) | ||||
| { | ||||
| 	unsigned int when; | ||||
| 	struct EventNode *event; | ||||
| 
 | ||||
| 	if (state->EventSet++ == 0) | ||||
| 		state->Now = ARMul_Time (state); | ||||
| 	when = (state->Now + delay) % EVENTLISTSIZE; | ||||
| 	event = (struct EventNode *) malloc (sizeof (struct EventNode)); | ||||
| 
 | ||||
| 	_dbg_assert_msg_(ARM11, event, "SKYEYE:ARMul_ScheduleEvent: malloc event error\n"); | ||||
| 
 | ||||
| 	event->func = what; | ||||
| 	event->next = *(state->EventPtr + when); | ||||
| 	*(state->EventPtr + when) = event; | ||||
| } | ||||
| 
 | ||||
| /* This routine is called at the beginning of
 | ||||
|    every cycle, to envoke scheduled events.  */ | ||||
| 
 | ||||
| void | ||||
| ARMul_EnvokeEvent (ARMul_State * state) | ||||
| { | ||||
| 	static unsigned int then; | ||||
| 
 | ||||
| 	then = state->Now; | ||||
| 	state->Now = ARMul_Time (state) % EVENTLISTSIZE; | ||||
| 	if (then < state->Now) | ||||
| 		/* Schedule events.  */ | ||||
| 		EnvokeList (state, then, state->Now); | ||||
| 	else if (then > state->Now) { | ||||
| 		/* Need to wrap around the list.  */ | ||||
| 		EnvokeList (state, then, EVENTLISTSIZE - 1L); | ||||
| 		EnvokeList (state, 0L, state->Now); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* Envokes all the entries in a range.  */ | ||||
| 
 | ||||
| static void | ||||
| EnvokeList (ARMul_State * state, unsigned int from, unsigned int to) | ||||
| { | ||||
| 	for (; from <= to; from++) { | ||||
| 		struct EventNode *anevent; | ||||
| 
 | ||||
| 		anevent = *(state->EventPtr + from); | ||||
| 		while (anevent) { | ||||
| 			(anevent->func) (state); | ||||
| 			state->EventSet--; | ||||
| 			anevent = anevent->next; | ||||
| 		} | ||||
| 		*(state->EventPtr + from) = NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* This routine is returns the number of clock ticks since the last reset.  */ | ||||
| 
 | ||||
| unsigned int | ||||
| ARMul_Time (ARMul_State * state) | ||||
| { | ||||
| 	return (state->NumScycles + state->NumNcycles + | ||||
| 		state->NumIcycles + state->NumCcycles + state->NumFcycles); | ||||
| } | ||||
							
								
								
									
										680
									
								
								src/core/src/arm/armvirt.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										680
									
								
								src/core/src/arm/armvirt.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,680 @@ | |||
| /*  armvirt.c -- ARMulator virtual memory interace:  ARM6 Instruction Emulator.
 | ||||
|     Copyright (C) 1994 Advanced RISC Machines Ltd. | ||||
|   | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
|   | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|   | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||||
| 
 | ||||
| /* This file contains a complete ARMulator memory model, modelling a
 | ||||
| "virtual memory" system. A much simpler model can be found in armfast.c, | ||||
| and that model goes faster too, but has a fixed amount of memory. This | ||||
| model's memory has 64K pages, allocated on demand from a 64K entry page | ||||
| table. The routines PutWord and GetWord implement this. Pages are never | ||||
| freed as they might be needed again. A single area of memory may be | ||||
| defined to generate aborts. */ | ||||
| 
 | ||||
| #include "armdefs.h" | ||||
| #include "skyeye_defs.h" | ||||
| //#include "code_cov.h"
 | ||||
| 
 | ||||
| #ifdef VALIDATE			/* for running the validate suite */ | ||||
| #define TUBE 48 * 1024 * 1024	/* write a char on the screen */ | ||||
| #define ABORTS 1 | ||||
| #endif | ||||
| 
 | ||||
| /* #define ABORTS */ | ||||
| 
 | ||||
| #ifdef ABORTS			/* the memory system will abort */ | ||||
| /* For the old test suite Abort between 32 Kbytes and 32 Mbytes
 | ||||
|    For the new test suite Abort between 8 Mbytes and 26 Mbytes */ | ||||
| /* #define LOWABORT 32 * 1024
 | ||||
| #define HIGHABORT 32 * 1024 * 1024 */ | ||||
| #define LOWABORT 8 * 1024 * 1024 | ||||
| #define HIGHABORT 26 * 1024 * 1024 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #define NUMPAGES 64 * 1024 | ||||
| #define PAGESIZE 64 * 1024 | ||||
| #define PAGEBITS 16 | ||||
| #define OFFSETBITS 0xffff | ||||
| //chy 2003-08-19: seems no use ????
 | ||||
| int SWI_vector_installed = FALSE; | ||||
| extern ARMword skyeye_cachetype; | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *        Get a byte into Virtual Memory, maybe allocating the page          * | ||||
| \***************************************************************************/ | ||||
| static fault_t | ||||
| GetByte (ARMul_State * state, ARMword address, ARMword * data) | ||||
| { | ||||
| 	fault_t fault; | ||||
| 
 | ||||
| 	fault = mmu_read_byte (state, address, data); | ||||
| 	if (fault) { | ||||
| //chy 2003-07-11: sometime has fault, but linux can continue running  !!!!????
 | ||||
| //              printf("SKYEYE: GetByte fault %d \n", fault);
 | ||||
| 	} | ||||
| 	return fault; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *        Get a halfword into Virtual Memory, maybe allocating the page          * | ||||
| \***************************************************************************/ | ||||
| static fault_t | ||||
| GetHalfWord (ARMul_State * state, ARMword address, ARMword * data) | ||||
| { | ||||
| 	fault_t fault; | ||||
| 
 | ||||
| 	fault = mmu_read_halfword (state, address, data); | ||||
| 	if (fault) { | ||||
| //chy 2003-07-11: sometime has fault, but linux can continue running  !!!!????
 | ||||
| //              printf("SKYEYE: GetHalfWord fault %d \n", fault);
 | ||||
| 	} | ||||
| 	return fault; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *        Get a Word from Virtual Memory, maybe allocating the page          * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| static fault_t | ||||
| GetWord (ARMul_State * state, ARMword address, ARMword * data) | ||||
| { | ||||
| 	fault_t fault; | ||||
| 
 | ||||
| 	fault = mmu_read_word (state, address, data); | ||||
| 	if (fault) { | ||||
| //chy 2003-07-11: sometime has fault, but linux can continue running  !!!!????
 | ||||
| #if 0 | ||||
| /* XXX */ extern int hack; | ||||
| 		hack = 1; | ||||
| #endif | ||||
| #if 0 | ||||
| 		printf ("mmu_read_word at 0x%08x: ", address); | ||||
| 		switch (fault) { | ||||
| 		case ALIGNMENT_FAULT: | ||||
| 			printf ("ALIGNMENT_FAULT"); | ||||
| 			break; | ||||
| 		case SECTION_TRANSLATION_FAULT: | ||||
| 			printf ("SECTION_TRANSLATION_FAULT"); | ||||
| 			break; | ||||
| 		case PAGE_TRANSLATION_FAULT: | ||||
| 			printf ("PAGE_TRANSLATION_FAULT"); | ||||
| 			break; | ||||
| 		case SECTION_DOMAIN_FAULT: | ||||
| 			printf ("SECTION_DOMAIN_FAULT"); | ||||
| 			break; | ||||
| 		case SECTION_PERMISSION_FAULT: | ||||
| 			printf ("SECTION_PERMISSION_FAULT"); | ||||
| 			break; | ||||
| 		case SUBPAGE_PERMISSION_FAULT: | ||||
| 			printf ("SUBPAGE_PERMISSION_FAULT"); | ||||
| 			break; | ||||
| 		default: | ||||
| 			printf ("Unrecognized fault number!"); | ||||
| 		} | ||||
| 		printf ("\tpc = 0x%08x\n", state->Reg[15]); | ||||
| #endif | ||||
| 	} | ||||
| 	return fault; | ||||
| } | ||||
| 
 | ||||
| //2003-07-10 chy: lyh change
 | ||||
| /****************************************************************************\
 | ||||
|  * 			Load a Instrion Word into Virtual Memory						* | ||||
| \****************************************************************************/ | ||||
| static fault_t | ||||
| LoadInstr (ARMul_State * state, ARMword address, ARMword * instr) | ||||
| { | ||||
| 	fault_t fault; | ||||
| 	fault = mmu_load_instr (state, address, instr); | ||||
| 	return fault; | ||||
| 	//if (fault)
 | ||||
| 	//      log_msg("load_instr fault = %d, address = %x\n", fault, address);
 | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *        Put a byte into Virtual Memory, maybe allocating the page          * | ||||
| \***************************************************************************/ | ||||
| static fault_t | ||||
| PutByte (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	fault_t fault; | ||||
| 
 | ||||
| 	fault = mmu_write_byte (state, address, data); | ||||
| 	if (fault) { | ||||
| //chy 2003-07-11: sometime has fault, but linux can continue running  !!!!????
 | ||||
| //              printf("SKYEYE: PutByte fault %d \n", fault);
 | ||||
| 	} | ||||
| 	return fault; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *        Put a halfword into Virtual Memory, maybe allocating the page          * | ||||
| \***************************************************************************/ | ||||
| static fault_t | ||||
| PutHalfWord (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	fault_t fault; | ||||
| 
 | ||||
| 	fault = mmu_write_halfword (state, address, data); | ||||
| 	if (fault) { | ||||
| //chy 2003-07-11: sometime has fault, but linux can continue running  !!!!????
 | ||||
| //              printf("SKYEYE: PutHalfWord fault %d \n", fault);
 | ||||
| 	} | ||||
| 	return fault; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *        Put a Word into Virtual Memory, maybe allocating the page          * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| static fault_t | ||||
| PutWord (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	fault_t fault; | ||||
| 
 | ||||
| 	fault = mmu_write_word (state, address, data); | ||||
| 	if (fault) { | ||||
| //chy 2003-07-11: sometime has fault, but linux can continue running  !!!!????
 | ||||
| #if 0 | ||||
| /* XXX */ extern int hack; | ||||
| 		hack = 1; | ||||
| #endif | ||||
| #if 0 | ||||
| 		printf ("mmu_write_word at 0x%08x: ", address); | ||||
| 		switch (fault) { | ||||
| 		case ALIGNMENT_FAULT: | ||||
| 			printf ("ALIGNMENT_FAULT"); | ||||
| 			break; | ||||
| 		case SECTION_TRANSLATION_FAULT: | ||||
| 			printf ("SECTION_TRANSLATION_FAULT"); | ||||
| 			break; | ||||
| 		case PAGE_TRANSLATION_FAULT: | ||||
| 			printf ("PAGE_TRANSLATION_FAULT"); | ||||
| 			break; | ||||
| 		case SECTION_DOMAIN_FAULT: | ||||
| 			printf ("SECTION_DOMAIN_FAULT"); | ||||
| 			break; | ||||
| 		case SECTION_PERMISSION_FAULT: | ||||
| 			printf ("SECTION_PERMISSION_FAULT"); | ||||
| 			break; | ||||
| 		case SUBPAGE_PERMISSION_FAULT: | ||||
| 			printf ("SUBPAGE_PERMISSION_FAULT"); | ||||
| 			break; | ||||
| 		default: | ||||
| 			printf ("Unrecognized fault number!"); | ||||
| 		} | ||||
| 		printf ("\tpc = 0x%08x\n", state->Reg[15]); | ||||
| #endif | ||||
| 	} | ||||
| 	return fault; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                      Initialise the memory interface                      * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| unsigned | ||||
| ARMul_MemoryInit (ARMul_State * state, unsigned int initmemsize) | ||||
| { | ||||
| 	return TRUE; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                         Remove the memory interface                       * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| void | ||||
| ARMul_MemoryExit (ARMul_State * state) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                   ReLoad Instruction                                     * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_ReLoadInstr (ARMul_State * state, ARMword address, ARMword isize) | ||||
| { | ||||
| 	ARMword data; | ||||
| 	fault_t fault; | ||||
| 
 | ||||
| #ifdef ABORTS | ||||
| 	if (address >= LOWABORT && address < HIGHABORT) { | ||||
| 		ARMul_PREFETCHABORT (address); | ||||
| 		return ARMul_ABORTWORD; | ||||
| 	} | ||||
| 	else { | ||||
| 		ARMul_CLEARABORT; | ||||
| 	} | ||||
| #endif | ||||
| #if 0 | ||||
| 	/* do profiling for code coverage */ | ||||
| 	if (skyeye_config.code_cov.prof_on) | ||||
| 			cov_prof(EXEC_FLAG, address); | ||||
| #endif | ||||
| #if 1 | ||||
| 	if ((isize == 2) && (address & 0x2)) { | ||||
| 		ARMword lo, hi; | ||||
| 		if (!(skyeye_cachetype == INSTCACHE)) | ||||
| 			fault = GetHalfWord (state, address, &lo); | ||||
| 		else | ||||
| 			fault = LoadInstr (state, address, &lo); | ||||
| #if 0 | ||||
| 		if (!fault) { | ||||
| 			if (!(skyeye_cachetype == INSTCACHE)) | ||||
| 				fault = GetHalfWord (state, address + isize, &hi); | ||||
| 			else | ||||
| 				fault = LoadInstr (state, address + isize, &hi); | ||||
| 
 | ||||
| 		} | ||||
| #endif | ||||
| 		if (fault) { | ||||
| 			ARMul_PREFETCHABORT (address); | ||||
| 			return ARMul_ABORTWORD; | ||||
| 		} | ||||
| 		else { | ||||
| 			ARMul_CLEARABORT; | ||||
| 		} | ||||
| 		return lo; | ||||
| #if 0 | ||||
| 		if (state->bigendSig == HIGH) | ||||
| 			return (lo << 16) | (hi >> 16); | ||||
| 		else | ||||
| 			return ((hi & 0xFFFF) << 16) | (lo >> 16); | ||||
| #endif | ||||
| 	} | ||||
| #endif | ||||
| 	if (!(skyeye_cachetype == INSTCACHE)) | ||||
| 		fault = GetWord (state, address, &data); | ||||
| 	else | ||||
| 		fault = LoadInstr (state, address, &data); | ||||
| 
 | ||||
| 	if (fault) { | ||||
| 
 | ||||
| 		/* dyf add for s3c6410 no instcache temporary 2010.9.17 */ | ||||
| 		if (!(skyeye_cachetype == INSTCACHE)) { | ||||
| 			/* set translation fault  on prefetch abort */ | ||||
| 			state->mmu.fault_statusi = fault  & 0xFF; | ||||
| 			state->mmu.fault_address = address; | ||||
| 		} | ||||
| 		/* add end */ | ||||
| 
 | ||||
| 		ARMul_PREFETCHABORT (address); | ||||
| 		return ARMul_ABORTWORD; | ||||
| 	} | ||||
| 	else { | ||||
| 		ARMul_CLEARABORT; | ||||
| 	} | ||||
| 
 | ||||
| 	return data; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                   Load Instruction, Sequential Cycle                      * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_LoadInstrS (ARMul_State * state, ARMword address, ARMword isize) | ||||
| { | ||||
| 	state->NumScycles++; | ||||
| 
 | ||||
| #ifdef HOURGLASS | ||||
| 	if ((state->NumScycles & HOURGLASS_RATE) == 0) { | ||||
| 		HOURGLASS; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	return ARMul_ReLoadInstr (state, address, isize); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                 Load Instruction, Non Sequential Cycle                    * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_LoadInstrN (ARMul_State * state, ARMword address, ARMword isize) | ||||
| { | ||||
| 	state->NumNcycles++; | ||||
| 
 | ||||
| 	return ARMul_ReLoadInstr (state, address, isize); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                      Read Word (but don't tell anyone!)                   * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_ReadWord (ARMul_State * state, ARMword address) | ||||
| { | ||||
| 	ARMword data; | ||||
| 	fault_t fault; | ||||
| 
 | ||||
| #ifdef ABORTS | ||||
| 	if (address >= LOWABORT && address < HIGHABORT) { | ||||
| 		ARMul_DATAABORT (address); | ||||
| 		return ARMul_ABORTWORD; | ||||
| 	} | ||||
| 	else { | ||||
| 		ARMul_CLEARABORT; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	fault = GetWord (state, address, &data); | ||||
| 	if (fault) { | ||||
| 		state->mmu.fault_status = | ||||
| 			(fault | (state->mmu.last_domain << 4)) & 0xFF; | ||||
| 		state->mmu.fault_address = address; | ||||
| 		ARMul_DATAABORT (address); | ||||
| 		return ARMul_ABORTWORD; | ||||
| 	} | ||||
| 	else { | ||||
| 		ARMul_CLEARABORT; | ||||
| 	} | ||||
| 	return data; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                        Load Word, Sequential Cycle                        * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_LoadWordS (ARMul_State * state, ARMword address) | ||||
| { | ||||
| 	state->NumScycles++; | ||||
| 
 | ||||
| 	return ARMul_ReadWord (state, address); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                      Load Word, Non Sequential Cycle                      * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_LoadWordN (ARMul_State * state, ARMword address) | ||||
| { | ||||
| 	state->NumNcycles++; | ||||
| 
 | ||||
| 	return ARMul_ReadWord (state, address); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                     Load Halfword, (Non Sequential Cycle)                 * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_LoadHalfWord (ARMul_State * state, ARMword address) | ||||
| { | ||||
| 	ARMword data; | ||||
| 	fault_t fault; | ||||
| 
 | ||||
| 	state->NumNcycles++; | ||||
| 	fault = GetHalfWord (state, address, &data); | ||||
| 
 | ||||
| 	if (fault) { | ||||
| 		state->mmu.fault_status = | ||||
| 			(fault | (state->mmu.last_domain << 4)) & 0xFF; | ||||
| 		state->mmu.fault_address = address; | ||||
| 		ARMul_DATAABORT (address); | ||||
| 		return ARMul_ABORTWORD; | ||||
| 	} | ||||
| 	else { | ||||
| 		ARMul_CLEARABORT; | ||||
| 	} | ||||
| 
 | ||||
| 	return data; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                      Read Byte (but don't tell anyone!)                   * | ||||
| \***************************************************************************/ | ||||
| int ARMul_ICE_ReadByte(ARMul_State * state, ARMword address, ARMword *presult) | ||||
| { | ||||
|  ARMword data; | ||||
|  fault_t fault; | ||||
|  fault = GetByte (state, address, &data); | ||||
|  if (fault) { | ||||
| 	 *presult=-1; fault=ALIGNMENT_FAULT; return fault; | ||||
|  }else{ | ||||
| 	 *(char *)presult=(unsigned char)(data & 0xff); fault=NO_FAULT; return fault; | ||||
|  } | ||||
| } | ||||
| 	  | ||||
|   | ||||
| ARMword | ||||
| ARMul_ReadByte (ARMul_State * state, ARMword address) | ||||
| { | ||||
| 	ARMword data; | ||||
| 	fault_t fault; | ||||
| 
 | ||||
| 	fault = GetByte (state, address, &data); | ||||
| 
 | ||||
| 	if (fault) { | ||||
| 		state->mmu.fault_status = | ||||
| 			(fault | (state->mmu.last_domain << 4)) & 0xFF; | ||||
| 		state->mmu.fault_address = address; | ||||
| 		ARMul_DATAABORT (address); | ||||
| 		return ARMul_ABORTWORD; | ||||
| 	} | ||||
| 	else { | ||||
| 		ARMul_CLEARABORT; | ||||
| 	} | ||||
| 
 | ||||
| 	return data; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                     Load Byte, (Non Sequential Cycle)                     * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_LoadByte (ARMul_State * state, ARMword address) | ||||
| { | ||||
| 	state->NumNcycles++; | ||||
| 
 | ||||
| 	return ARMul_ReadByte (state, address); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                     Write Word (but don't tell anyone!)                   * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| void | ||||
| ARMul_WriteWord (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	fault_t fault; | ||||
| 
 | ||||
| #ifdef ABORTS | ||||
| 	if (address >= LOWABORT && address < HIGHABORT) { | ||||
| 		ARMul_DATAABORT (address); | ||||
| 		return; | ||||
| 	} | ||||
| 	else { | ||||
| 		ARMul_CLEARABORT; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	fault = PutWord (state, address, data); | ||||
| 	if (fault) { | ||||
| 		state->mmu.fault_status = | ||||
| 			(fault | (state->mmu.last_domain << 4)) & 0xFF; | ||||
| 		state->mmu.fault_address = address; | ||||
| 		ARMul_DATAABORT (address); | ||||
| 		return; | ||||
| 	} | ||||
| 	else { | ||||
| 		ARMul_CLEARABORT; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                       Store Word, Sequential Cycle                        * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| void | ||||
| ARMul_StoreWordS (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	state->NumScycles++; | ||||
| 
 | ||||
| 	ARMul_WriteWord (state, address, data); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                       Store Word, Non Sequential Cycle                        * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| void | ||||
| ARMul_StoreWordN (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	state->NumNcycles++; | ||||
| 
 | ||||
| 	ARMul_WriteWord (state, address, data); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                    Store HalfWord, (Non Sequential Cycle)                 * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| void | ||||
| ARMul_StoreHalfWord (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	fault_t fault; | ||||
| 	state->NumNcycles++; | ||||
| 	fault = PutHalfWord (state, address, data); | ||||
| 	if (fault) { | ||||
| 		state->mmu.fault_status = | ||||
| 			(fault | (state->mmu.last_domain << 4)) & 0xFF; | ||||
| 		state->mmu.fault_address = address; | ||||
| 		ARMul_DATAABORT (address); | ||||
| 		return; | ||||
| 	} | ||||
| 	else { | ||||
| 		ARMul_CLEARABORT; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| //chy 2006-04-15 
 | ||||
| int ARMul_ICE_WriteByte (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	fault_t fault; | ||||
| 	fault = PutByte (state, address, data); | ||||
| 	if (fault)  | ||||
| 		return 1;  | ||||
| 	else  | ||||
| 		return 0; | ||||
| } | ||||
| /***************************************************************************\
 | ||||
| *                     Write Byte (but don't tell anyone!)                   * | ||||
| \***************************************************************************/ | ||||
| //chy 2003-07-10, add real write byte fun
 | ||||
| void | ||||
| ARMul_WriteByte (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	fault_t fault; | ||||
| 	fault = PutByte (state, address, data); | ||||
| 	if (fault) { | ||||
| 		state->mmu.fault_status = | ||||
| 			(fault | (state->mmu.last_domain << 4)) & 0xFF; | ||||
| 		state->mmu.fault_address = address; | ||||
| 		ARMul_DATAABORT (address); | ||||
| 		return; | ||||
| 	} | ||||
| 	else { | ||||
| 		ARMul_CLEARABORT; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                    Store Byte, (Non Sequential Cycle)                     * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| void | ||||
| ARMul_StoreByte (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	state->NumNcycles++; | ||||
| 
 | ||||
| #ifdef VALIDATE | ||||
| 	if (address == TUBE) { | ||||
| 		if (data == 4) | ||||
| 			state->Emulate = FALSE; | ||||
| 		else | ||||
| 			(void) putc ((char) data, stderr);	/* Write Char */ | ||||
| 		return; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	ARMul_WriteByte (state, address, data); | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                   Swap Word, (Two Non Sequential Cycles)                  * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_SwapWord (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	ARMword temp; | ||||
| 
 | ||||
| 	state->NumNcycles++; | ||||
| 
 | ||||
| 	temp = ARMul_ReadWord (state, address); | ||||
| 
 | ||||
| 	state->NumNcycles++; | ||||
| 
 | ||||
| 	PutWord (state, address, data); | ||||
| 
 | ||||
| 	return temp; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                   Swap Byte, (Two Non Sequential Cycles)                  * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| ARMword | ||||
| ARMul_SwapByte (ARMul_State * state, ARMword address, ARMword data) | ||||
| { | ||||
| 	ARMword temp; | ||||
| 
 | ||||
| 	temp = ARMul_LoadByte (state, address); | ||||
| 	ARMul_StoreByte (state, address, data); | ||||
| 
 | ||||
| 	return temp; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                             Count I Cycles                                * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| void | ||||
| ARMul_Icycles (ARMul_State * state, unsigned number, | ||||
| 	       ARMword address) | ||||
| { | ||||
| 	state->NumIcycles += number; | ||||
| 	ARMul_CLEARABORT; | ||||
| } | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                             Count C Cycles                                * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| void | ||||
| ARMul_Ccycles (ARMul_State * state, unsigned number, | ||||
| 	       ARMword address) | ||||
| { | ||||
| 	state->NumCcycles += number; | ||||
| 	ARMul_CLEARABORT; | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue