mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30: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> |   <ItemGroup> | ||||||
|     <ClCompile Include="src\arm\armemu.cpp" /> |     <ClCompile Include="src\arm\armemu.cpp" /> | ||||||
|     <ClCompile Include="src\arm\arminit.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\arm\disassembler\arm_disasm.cpp" /> | ||||||
|     <ClCompile Include="src\core.cpp" /> |     <ClCompile Include="src\core.cpp" /> | ||||||
|     <ClCompile Include="src\core_timing.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\directory_file_system.cpp" /> | ||||||
|     <ClCompile Include="src\file_sys\meta_file_system.cpp" /> |     <ClCompile Include="src\file_sys\meta_file_system.cpp" /> | ||||||
|     <ClCompile Include="src\loader.cpp" /> |     <ClCompile Include="src\loader.cpp" /> | ||||||
|  | @ -165,7 +170,8 @@ | ||||||
|     <ClInclude Include="src\arm\skyeye_defs.h" /> |     <ClInclude Include="src\arm\skyeye_defs.h" /> | ||||||
|     <ClInclude Include="src\core.h" /> |     <ClInclude Include="src\core.h" /> | ||||||
|     <ClInclude Include="src\core_timing.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\directory_file_system.h" /> | ||||||
|     <ClInclude Include="src\file_sys\file_sys.h" /> |     <ClInclude Include="src\file_sys\file_sys.h" /> | ||||||
|     <ClInclude Include="src\file_sys\meta_file_system.h" /> |     <ClInclude Include="src\file_sys\meta_file_system.h" /> | ||||||
|  |  | ||||||
|  | @ -22,6 +22,21 @@ | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|     <ClCompile Include="src\system.cpp" /> |     <ClCompile Include="src\system.cpp" /> | ||||||
|     <ClCompile Include="src\core_timing.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> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Filter Include="arm"> |     <Filter Include="arm"> | ||||||
|  | @ -94,7 +109,10 @@ | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|     <ClInclude Include="src\system.h" /> |     <ClInclude Include="src\system.h" /> | ||||||
|     <ClInclude Include="src\core_timing.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> |       <Filter>elf</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |  | ||||||
|  | @ -21,6 +21,19 @@ | ||||||
| #include "armemu.h" | #include "armemu.h" | ||||||
| #include "armos.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_callback.h"
 | ||||||
| //#include "skyeye_bus.h"
 | //#include "skyeye_bus.h"
 | ||||||
| //#include "sim_control.h"
 | //#include "sim_control.h"
 | ||||||
|  | @ -2174,10 +2187,10 @@ ARMul_Emulate26 (ARMul_State * state) | ||||||
| 								(state, | 								(state, | ||||||
| 								 ARMul_CP15_R5_MMU_EXCPT, | 								 ARMul_CP15_R5_MMU_EXCPT, | ||||||
| 								 pc); | 								 pc); | ||||||
| 							if (!XScale_debug_moe | 							//if (!XScale_debug_moe
 | ||||||
| 							    (state, | 							//    (state,
 | ||||||
| 							     ARMul_CP14_R10_MOE_BT)) | 							//     ARMul_CP14_R10_MOE_BT))
 | ||||||
| 								break; | 							//	break; // Disabled /bunnei
 | ||||||
| 						} | 						} | ||||||
| 
 | 
 | ||||||
| 						/* Force the next instruction to be refetched.  */ | 						/* Force the next instruction to be refetched.  */ | ||||||
|  |  | ||||||
|  | @ -73,6 +73,7 @@ extern ARMword isize; | ||||||
| #define ASSIGNT(res) state->TFlag = res | #define ASSIGNT(res) state->TFlag = res | ||||||
| #define INSN_SIZE (TFLAG ? 2 : 4) | #define INSN_SIZE (TFLAG ? 2 : 4) | ||||||
| #else | #else | ||||||
|  | #define TBIT (1L << 5) | ||||||
| #define INSN_SIZE 4 | #define INSN_SIZE 4 | ||||||
| #define TFLAG 0 | #define TFLAG 0 | ||||||
| #endif | #endif | ||||||
|  | @ -229,12 +230,12 @@ extern ARMword isize; | ||||||
|     }									\ |     }									\ | ||||||
|   while (0) |   while (0) | ||||||
| 
 | 
 | ||||||
| #ifndef MODE32 | //#ifndef MODE32
 | ||||||
| #define VECTORS 0x20 | #define VECTORS 0x20 | ||||||
| #define LEGALADDR 0x03ffffff | #define LEGALADDR 0x03ffffff | ||||||
| #define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig) | #define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig) | ||||||
| #define ADDREXCEPT(address)   (address > LEGALADDR && !state->data32Sig) | #define ADDREXCEPT(address)   (address > LEGALADDR && !state->data32Sig) | ||||||
| #endif | //#endif
 | ||||||
| 
 | 
 | ||||||
| #define INTERNALABORT(address)			\ | #define INTERNALABORT(address)			\ | ||||||
|   do						\ |   do						\ | ||||||
|  | @ -409,10 +410,12 @@ extern ARMword isize; | ||||||
|      || (! (STATE)->is_XScale)				\ |      || (! (STATE)->is_XScale)				\ | ||||||
|      || (read_cp15_reg (15, 0, 1) & (1 << (CP)))) |      || (read_cp15_reg (15, 0, 1) & (1 << (CP)))) | ||||||
| */ | */ | ||||||
| #define CP_ACCESS_ALLOWED(STATE, CP)			\ | //#define CP_ACCESS_ALLOWED(STATE, CP)			\ | ||||||
|     (   ((CP) >= 14)					\ | //	(((CP) >= 14)					\ | ||||||
|      || (! (STATE)->is_XScale)				\ | //	|| (!(STATE)->is_XScale)				\ | ||||||
|      || (xscale_cp15_cp_access_allowed(STATE,15,CP))) | //	|| (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.  */ | /* Macro to rotate n right by b bits.  */ | ||||||
| #define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b)))) | #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
 | 	/* Only initialse the coprocessor support once we
 | ||||||
| 	   know what kind of chip we are dealing with.  */ | 	   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; | 	state->NumFcycles = 0; | ||||||
| 
 | 
 | ||||||
| 	//fprintf(stderr,"armul_reset 3: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);  
 | 	//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);  
 | 	//fprintf(stderr,"armul_reset 4: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);  
 | ||||||
| 
 | 
 | ||||||
| 	//mem_reset (state); /* move to memory/ram.c */
 | 	//mem_reset (state); /* move to memory/ram.c */
 | ||||||
|  | @ -436,7 +436,8 @@ ARMul_DoProg (ARMul_State * state) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		else { | 		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-02-22, should test debugmode first
 | ||||||
| 		//chy 2006-04-14, put below codes in ARMul_Emulate
 | 		//chy 2006-04-14, put below codes in ARMul_Emulate
 | ||||||
|  | @ -489,8 +490,10 @@ ARMul_DoInstr (ARMul_State * state) | ||||||
| #endif | #endif | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	else | 	else { | ||||||
| 		pc = ARMul_Emulate26 (state); | 		//pc = ARMul_Emulate26 (state); Commented out /bunnei
 | ||||||
|  | 		ERROR_LOG(ARM11, "Unsupported ARM 26-bit Mode!"); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	return (pc); | 	return (pc); | ||||||
| } | } | ||||||
|  | @ -501,78 +504,78 @@ ARMul_DoInstr (ARMul_State * state) | ||||||
| * appropriate vector's memory address (0,4,8 ....)                          * | * appropriate vector's memory address (0,4,8 ....)                          * | ||||||
| \***************************************************************************/ | \***************************************************************************/ | ||||||
| 
 | 
 | ||||||
| //void
 | void | ||||||
| //ARMul_Abort (ARMul_State * state, ARMword vector)
 | ARMul_Abort (ARMul_State * state, ARMword vector) | ||||||
| //{
 | { | ||||||
| //	ARMword temp;
 | 	ARMword temp; | ||||||
| //	int isize = INSN_SIZE;
 | 	int isize = INSN_SIZE; | ||||||
| //	int esize = (TFLAG ? 0 : 4);
 | 	int esize = (TFLAG ? 0 : 4); | ||||||
| //	int e2size = (TFLAG ? -4 : 0);
 | 	int e2size = (TFLAG ? -4 : 0); | ||||||
| //
 | 
 | ||||||
| //	state->Aborted = FALSE;
 | 	state->Aborted = FALSE; | ||||||
| //
 | 
 | ||||||
| //	if (state->prog32Sig)
 | 	if (state->prog32Sig) | ||||||
| //		if (ARMul_MODE26BIT)
 | 		if (ARMul_MODE26BIT) | ||||||
| //			temp = R15PC;
 | 			temp = R15PC; | ||||||
| //		else
 | 		else | ||||||
| //			temp = state->Reg[15];
 | 			temp = state->Reg[15]; | ||||||
| //	else
 | 	else | ||||||
| //		temp = R15PC | ECC | ER15INT | EMODE;
 | 		temp = R15PC | ECC | ER15INT | EMODE; | ||||||
| //
 | 
 | ||||||
| //	switch (vector) {
 | 	switch (vector) { | ||||||
| //	case ARMul_ResetV:	/* RESET */
 | 	case ARMul_ResetV:	/* RESET */ | ||||||
| //		SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE,
 | 		SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE, | ||||||
| //			  0);
 | 			  0); | ||||||
| //		break;
 | 		break; | ||||||
| //	case ARMul_UndefinedInstrV:	/* Undefined Instruction */
 | 	case ARMul_UndefinedInstrV:	/* Undefined Instruction */ | ||||||
| //		SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE,
 | 		SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE, | ||||||
| //			  isize);
 | 			  isize); | ||||||
| //		break;
 | 		break; | ||||||
| //	case ARMul_SWIV:	/* Software Interrupt */
 | 	case ARMul_SWIV:	/* Software Interrupt */ | ||||||
| //		SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE,
 | 		SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE, | ||||||
| //			  isize);
 | 			  isize); | ||||||
| //		break;
 | 		break; | ||||||
| //	case ARMul_PrefetchAbortV:	/* Prefetch Abort */
 | 	case ARMul_PrefetchAbortV:	/* Prefetch Abort */ | ||||||
| //		state->AbortAddr = 1;
 | 		state->AbortAddr = 1; | ||||||
| //		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE,
 | 		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, | ||||||
| //			  esize);
 | 			  esize); | ||||||
| //		break;
 | 		break; | ||||||
| //	case ARMul_DataAbortV:	/* Data Abort */
 | 	case ARMul_DataAbortV:	/* Data Abort */ | ||||||
| //		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE,
 | 		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, | ||||||
| //			  e2size);
 | 			  e2size); | ||||||
| //		break;
 | 		break; | ||||||
| //	case ARMul_AddrExceptnV:	/* Address Exception */
 | 	case ARMul_AddrExceptnV:	/* Address Exception */ | ||||||
| //		SETABORT (IBIT, SVC26MODE, isize);
 | 		SETABORT (IBIT, SVC26MODE, isize); | ||||||
| //		break;
 | 		break; | ||||||
| //	case ARMul_IRQV:	/* IRQ */
 | 	case ARMul_IRQV:	/* IRQ */ | ||||||
| //		//chy 2003-09-02 the if sentence seems no use
 | 		//chy 2003-09-02 the if sentence seems no use
 | ||||||
| //#if 0
 | #if 0 | ||||||
| //		if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp)
 | 		if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) | ||||||
| //		    || (temp & ARMul_CP13_R0_IRQ))
 | 		    || (temp & ARMul_CP13_R0_IRQ)) | ||||||
| //#endif
 | #endif | ||||||
| //			SETABORT (IBIT,
 | 			SETABORT (IBIT, | ||||||
| //				  state->prog32Sig ? IRQ32MODE : IRQ26MODE,
 | 				  state->prog32Sig ? IRQ32MODE : IRQ26MODE, | ||||||
| //				  esize);
 | 				  esize); | ||||||
| //		break;
 | 		break; | ||||||
| //	case ARMul_FIQV:	/* FIQ */
 | 	case ARMul_FIQV:	/* FIQ */ | ||||||
| //		//chy 2003-09-02 the if sentence seems no use
 | 		//chy 2003-09-02 the if sentence seems no use
 | ||||||
| //#if 0
 | #if 0 | ||||||
| //		if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp)
 | 		if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) | ||||||
| //		    || (temp & ARMul_CP13_R0_FIQ))
 | 		    || (temp & ARMul_CP13_R0_FIQ)) | ||||||
| //#endif
 | #endif | ||||||
| //			SETABORT (INTBITS,
 | 			SETABORT (INTBITS, | ||||||
| //				  state->prog32Sig ? FIQ32MODE : FIQ26MODE,
 | 				  state->prog32Sig ? FIQ32MODE : FIQ26MODE, | ||||||
| //				  esize);
 | 				  esize); | ||||||
| //		break;
 | 		break; | ||||||
| //	}
 | 	} | ||||||
| //
 | 
 | ||||||
| //	if (ARMul_MODE32BIT) {
 | 	if (ARMul_MODE32BIT) { | ||||||
| //		if (state->mmu.control & CONTROL_VECTOR)
 | 		if (state->mmu.control & CONTROL_VECTOR) | ||||||
| //			vector += 0xffff0000;	//for v4 high exception  address
 | 			vector += 0xffff0000;	//for v4 high exception  address
 | ||||||
| //		if (state->vector_remap_flag)
 | 		if (state->vector_remap_flag) | ||||||
| //			vector += state->vector_remap_addr; /* support some remap function in LPC processor */
 | 			vector += state->vector_remap_addr; /* support some remap function in LPC processor */ | ||||||
| //		ARMul_SetR15 (state, vector);
 | 		ARMul_SetR15 (state, vector); | ||||||
| //	}
 | 	} | ||||||
| //	else
 | 	else | ||||||
| //		ARMul_SetR15 (state, R15CCINTMODE | vector);
 | 		ARMul_SetR15 (state, R15CCINTMODE | vector); | ||||||
| //}
 | } | ||||||
|  |  | ||||||
|  | @ -45,55 +45,51 @@ mmu_init (ARMul_State * state) | ||||||
| 	state->mmu.process_id = 0; | 	state->mmu.process_id = 0; | ||||||
| 
 | 
 | ||||||
| 	switch (state->cpu->cpu_val & state->cpu->cpu_mask) { | 	switch (state->cpu->cpu_val & state->cpu->cpu_mask) { | ||||||
| 	case SA1100: | 	//case SA1100:
 | ||||||
| 	case SA1110: | 	//case SA1110:
 | ||||||
| 		SKYEYE_INFO("SKYEYE: use sa11xx mmu ops\n"); | 	//	NOTICE_LOG(ARM11, "SKYEYE: use sa11xx mmu ops\n");
 | ||||||
| 		state->mmu.ops = sa_mmu_ops; | 	//	state->mmu.ops = sa_mmu_ops;
 | ||||||
| 		break; | 	//	break;
 | ||||||
| 	case PXA250: | 	//case PXA250:
 | ||||||
| 	case PXA270:		//xscale
 | 	//case PXA270:		//xscale
 | ||||||
| 		SKYEYE_INFO ("SKYEYE: use xscale mmu ops\n"); | 	//	NOTICE_LOG(ARM11, "SKYEYE: use xscale mmu ops\n");
 | ||||||
| 		state->mmu.ops = xscale_mmu_ops; | 	//	state->mmu.ops = xscale_mmu_ops;
 | ||||||
| 		break; | 	//	break;
 | ||||||
| 	case 0x41807200:	//arm720t
 | 	//case 0x41807200:	//arm720t
 | ||||||
| 	case 0x41007700:	//arm7tdmi
 | 	//case 0x41007700:	//arm7tdmi
 | ||||||
| 	case 0x41007100:	//arm7100
 | 	//case 0x41007100:	//arm7100
 | ||||||
| 		SKYEYE_INFO ( "SKYEYE: use arm7100 mmu ops\n"); | 	//	NOTICE_LOG(ARM11,  "SKYEYE: use arm7100 mmu ops\n");
 | ||||||
| 		state->mmu.ops = arm7100_mmu_ops; | 	//	state->mmu.ops = arm7100_mmu_ops;
 | ||||||
| 		break; | 	//	break;
 | ||||||
| 	case 0x41009200: | 	//case 0x41009200:
 | ||||||
| 		SKYEYE_INFO ("SKYEYE: use arm920t mmu ops\n"); | 	//	NOTICE_LOG(ARM11, "SKYEYE: use arm920t mmu ops\n");
 | ||||||
| 		state->mmu.ops = arm920t_mmu_ops; | 	//	state->mmu.ops = arm920t_mmu_ops;
 | ||||||
| 		break; | 	//	break;
 | ||||||
| 	case 0x41069260: | 	//case 0x41069260:
 | ||||||
| 		SKYEYE_INFO ("SKYEYE: use arm926ejs mmu ops\n"); | 	//	NOTICE_LOG(ARM11, "SKYEYE: use arm926ejs mmu ops\n");
 | ||||||
| 		state->mmu.ops = arm926ejs_mmu_ops; | 	//	state->mmu.ops = arm926ejs_mmu_ops;
 | ||||||
| 		break; | 	//	break;
 | ||||||
| 	/* case 0x560f5810: */ | 	/* case 0x560f5810: */ | ||||||
| 	case 0x0007b000: | 	case 0x0007b000: | ||||||
| 		SKYEYE_INFO ("SKYEYE: use arm11jzf-s mmu ops\n"); | 		NOTICE_LOG(ARM11, "SKYEYE: use arm11jzf-s mmu ops\n"); | ||||||
| 		state->mmu.ops = arm1176jzf_s_mmu_ops; | 		//state->mmu.ops = arm1176jzf_s_mmu_ops;
 | ||||||
|  | 		_dbg_assert_msg_(ARM11, false, "ImplementMe: arm1176jzf_s_mmu_ops!"); | ||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
| 	case 0xc090: |  | ||||||
| 		SKYEYE_INFO ("SKYEYE: use cortex_a9 mmu ops\n"); |  | ||||||
| 		state->mmu.ops = cortex_a9_mmu_ops; |  | ||||||
| 		break; |  | ||||||
| 	default: | 	default: | ||||||
| 		fprintf (stderr, | 		ERROR_LOG (ARM11, | ||||||
| 			 "SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n", | 			 "SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n", | ||||||
| 			 state->cpu->cpu_val & state->cpu->cpu_mask); | 			 state->cpu->cpu_val & state->cpu->cpu_mask); | ||||||
| 		skyeye_exit (-1); |  | ||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
| 	}; | 	}; | ||||||
| 	ret = state->mmu.ops.init (state); | 	ret = state->mmu.ops.init (state); | ||||||
| 	state->mmu_inited = (ret == 0); | 	state->mmu_inited = (ret == 0); | ||||||
| 	/* initialize mmu_read and mmu_write for disassemble */ | 	/* initialize mmu_read and mmu_write for disassemble */ | ||||||
| 	skyeye_config_t *config  = get_current_config(); | 	//skyeye_config_t *config  = get_current_config();
 | ||||||
| 	generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name); | 	//generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name);
 | ||||||
| 	arch_instance->mmu_read = arm_mmu_read; | 	//arch_instance->mmu_read = arm_mmu_read;
 | ||||||
| 	arch_instance->mmu_write = arm_mmu_write; | 	//arch_instance->mmu_write = arm_mmu_write;
 | ||||||
| 
 | 
 | ||||||
| 	return ret; | 	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)); | 	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) | //
 | ||||||
| { | ///* dis_mmu_read for disassemble */
 | ||||||
| 	ARMul_State *state; | //exception_t arm_mmu_read(short size, uint32_t addr, uint32_t * value)
 | ||||||
| 	ARM_CPU_State *cpu = get_current_cpu(); | //{
 | ||||||
| 	state = &cpu->core[0]; | //	ARMul_State *state;
 | ||||||
| 	switch(size){ | //	ARM_CPU_State *cpu = get_current_cpu();
 | ||||||
| 	case 8: | //	state = &cpu->core[0];
 | ||||||
| 		MMU_OPS.read_byte (state, addr, value); | //	switch(size){
 | ||||||
| 		break; | //	case 8:
 | ||||||
| 	case 16: | //		MMU_OPS.read_byte (state, addr, value);
 | ||||||
| 	case 32: | //		break;
 | ||||||
| 		break; | //	case 16:
 | ||||||
| 	default: | //	case 32:
 | ||||||
| 		printf("In %s error size %d Line %d\n", __func__, size, __LINE__); | //		break;
 | ||||||
| 		break; | //	default:
 | ||||||
| 	} | //		ERROR_LOG(ARM11, "Error size %d", size);
 | ||||||
| 	return No_exp; | //		break;
 | ||||||
| } | //	}
 | ||||||
| /* dis_mmu_write for disassemble */ | //	return No_exp;
 | ||||||
| exception_t arm_mmu_write(short size, generic_address_t addr, uint32_t *value) | //}
 | ||||||
| { | ///* dis_mmu_write for disassemble */
 | ||||||
| 	ARMul_State *state; | //exception_t arm_mmu_write(short size, uint32_t addr, uint32_t *value)
 | ||||||
| 	ARM_CPU_State *cpu = get_current_cpu(); | //{
 | ||||||
| 		state = &cpu->core[0]; | //	ARMul_State *state;
 | ||||||
| 	switch(size){ | //	ARM_CPU_State *cpu = get_current_cpu();
 | ||||||
| 	case 8: | //		state = &cpu->core[0];
 | ||||||
| 		MMU_OPS.write_byte (state, addr, value); | //	switch(size){
 | ||||||
| 		break; | //	case 8:
 | ||||||
| 	case 16: | //		MMU_OPS.write_byte (state, addr, value);
 | ||||||
| 	case 32: | //		break;
 | ||||||
| 		break; | //	case 16:
 | ||||||
| 	default: | //	case 32:
 | ||||||
| 		printf("In %s error size %d Line %d\n", __func__, size, __LINE__); | //		break;
 | ||||||
| 		break; | //	default:
 | ||||||
| 	} | //		printf("In %s error size %d Line %d\n", __func__, size, __LINE__);
 | ||||||
| 	return No_exp; | //		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