diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/core.vcxproj | 14 | ||||
| -rw-r--r-- | src/core/core.vcxproj.filters | 48 | ||||
| -rw-r--r-- | src/core/src/arm/arm_regformat.h | 103 | ||||
| -rw-r--r-- | src/core/src/arm/armcpu.h | 83 | ||||
| -rw-r--r-- | src/core/src/arm/armdefs.h | 930 | ||||
| -rw-r--r-- | src/core/src/arm/armemu.cpp | 6618 | ||||
| -rw-r--r-- | src/core/src/arm/armemu.h | 657 | ||||
| -rw-r--r-- | src/core/src/arm/arminit.cpp | 578 | ||||
| -rw-r--r-- | src/core/src/arm/armmmu.cpp | 241 | ||||
| -rw-r--r-- | src/core/src/arm/armmmu.h | 254 | ||||
| -rw-r--r-- | src/core/src/arm/armos.h | 138 | ||||
| -rw-r--r-- | src/core/src/arm/mmu/arm1176jzf_s_mmu.c | 1165 | ||||
| -rw-r--r-- | src/core/src/arm/mmu/arm1176jzf_s_mmu.h | 37 | ||||
| -rw-r--r-- | src/core/src/arm/mmu/cache.h | 168 | ||||
| -rw-r--r-- | src/core/src/arm/mmu/rb.h | 55 | ||||
| -rw-r--r-- | src/core/src/arm/mmu/tlb.h | 94 | ||||
| -rw-r--r-- | src/core/src/arm/mmu/wb.h | 63 | ||||
| -rw-r--r-- | src/core/src/arm/skyeye_defs.h | 110 | 
18 files changed, 11356 insertions, 0 deletions
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index b457cc6e9..147cfc66d 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -133,12 +133,26 @@      </ProjectReference>    </ItemGroup>    <ItemGroup> +    <ClCompile Include="src\arm\armemu.cpp" /> +    <ClCompile Include="src\arm\arminit.cpp" />      <ClCompile Include="src\arm\disassembler\arm_disasm.cpp" />      <ClCompile Include="src\core.cpp" />      <ClCompile Include="src\mem_map.cpp" />    </ItemGroup>    <ItemGroup> +    <ClInclude Include="src\arm\armcpu.h" /> +    <ClInclude Include="src\arm\armdefs.h" /> +    <ClInclude Include="src\arm\armemu.h" /> +    <ClInclude Include="src\arm\armmmu.h" /> +    <ClInclude Include="src\arm\armos.h" /> +    <ClInclude Include="src\arm\arm_regformat.h" />      <ClInclude Include="src\arm\disassembler\arm_disasm.h" /> +    <ClInclude Include="src\arm\mmu\arm1176jzf_s_mmu.h" /> +    <ClInclude Include="src\arm\mmu\cache.h" /> +    <ClInclude Include="src\arm\mmu\rb.h" /> +    <ClInclude Include="src\arm\mmu\tlb.h" /> +    <ClInclude Include="src\arm\mmu\wb.h" /> +    <ClInclude Include="src\arm\skyeye_defs.h" />      <ClInclude Include="src\core.h" />      <ClInclude Include="src\mem_map.h" />    </ItemGroup> diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 9d981b995..b262708fc 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -6,6 +6,12 @@        <Filter>arm\disassembler</Filter>      </ClCompile>      <ClCompile Include="src\mem_map.cpp" /> +    <ClCompile Include="src\arm\arminit.cpp"> +      <Filter>arm</Filter> +    </ClCompile> +    <ClCompile Include="src\arm\armemu.cpp"> +      <Filter>arm</Filter> +    </ClCompile>    </ItemGroup>    <ItemGroup>      <Filter Include="arm"> @@ -14,6 +20,9 @@      <Filter Include="arm\disassembler">        <UniqueIdentifier>{61100188-a726-4024-ab16-95ee242b446e}</UniqueIdentifier>      </Filter> +    <Filter Include="arm\mmu"> +      <UniqueIdentifier>{a64d3c8a-747a-491b-b782-6e2622bedf24}</UniqueIdentifier> +    </Filter>    </ItemGroup>    <ItemGroup>      <ClInclude Include="src\arm\disassembler\arm_disasm.h"> @@ -21,5 +30,44 @@      </ClInclude>      <ClInclude Include="src\mem_map.h" />      <ClInclude Include="src\core.h" /> +    <ClInclude Include="src\arm\armdefs.h"> +      <Filter>arm</Filter> +    </ClInclude> +    <ClInclude Include="src\arm\armemu.h"> +      <Filter>arm</Filter> +    </ClInclude> +    <ClInclude Include="src\arm\skyeye_defs.h"> +      <Filter>arm</Filter> +    </ClInclude> +    <ClInclude Include="src\arm\arm_regformat.h"> +      <Filter>arm</Filter> +    </ClInclude> +    <ClInclude Include="src\arm\armos.h"> +      <Filter>arm</Filter> +    </ClInclude> +    <ClInclude Include="src\arm\armmmu.h"> +      <Filter>arm</Filter> +    </ClInclude> +    <ClInclude Include="src\arm\armcpu.h"> +      <Filter>arm</Filter> +    </ClInclude> +    <ClInclude Include="src\arm\mmu\arm1176jzf_s_mmu.h"> +      <Filter>arm\mmu</Filter> +    </ClInclude> +    <ClInclude Include="src\arm\mmu\cache.h"> +      <Filter>arm\mmu</Filter> +    </ClInclude> +    <ClInclude Include="src\arm\mmu\rb.h"> +      <Filter>arm\mmu</Filter> +    </ClInclude> +    <ClInclude Include="src\arm\mmu\tlb.h"> +      <Filter>arm\mmu</Filter> +    </ClInclude> +    <ClInclude Include="src\arm\mmu\wb.h"> +      <Filter>arm\mmu</Filter> +    </ClInclude> +  </ItemGroup> +  <ItemGroup> +    <None Include="CMakeLists.txt" />    </ItemGroup>  </Project>
\ No newline at end of file diff --git a/src/core/src/arm/arm_regformat.h b/src/core/src/arm/arm_regformat.h new file mode 100644 index 000000000..c7d6a87e0 --- /dev/null +++ b/src/core/src/arm/arm_regformat.h @@ -0,0 +1,103 @@ +#ifndef __ARM_REGFORMAT_H__ +#define __ARM_REGFORMAT_H__ + +enum arm_regno{ +	R0 = 0, +	R1, +	R2, +	R3, +	R4, +	R5, +	R6, +	R7, +	R8, +	R9, +	R10, +	R11, +	R12, +	R13, +	LR, +	R15, //PC, +	CPSR_REG, +	SPSR_REG, +#if 1 +	PHYS_PC, +	R13_USR, +	R14_USR, +	R13_SVC, +	R14_SVC, +	R13_ABORT, +	R14_ABORT, +	R13_UNDEF, +	R14_UNDEF, +	R13_IRQ, +	R14_IRQ, +	R8_FIRQ, +	R9_FIRQ, +	R10_FIRQ, +	R11_FIRQ, +	R12_FIRQ, +	R13_FIRQ, +	R14_FIRQ, +	SPSR_INVALID1, +	SPSR_INVALID2, +	SPSR_SVC, +	SPSR_ABORT, +	SPSR_UNDEF, +	SPSR_IRQ, +	SPSR_FIRQ, +	MODE_REG, /* That is the cpsr[4 : 0], just for calculation easily */ +	BANK_REG, +	EXCLUSIVE_TAG, +	EXCLUSIVE_STATE, +	EXCLUSIVE_RESULT, +	CP15_BASE, +	CP15_C0 = CP15_BASE, +	CP15_C0_C0 = CP15_C0, +	CP15_MAIN_ID = CP15_C0_C0, +	CP15_CACHE_TYPE, +	CP15_TCM_STATUS, +	CP15_TLB_TYPE, +	CP15_C0_C1, +	CP15_PROCESSOR_FEATURE_0 = CP15_C0_C1, +	CP15_PROCESSOR_FEATURE_1, +	CP15_DEBUG_FEATURE_0, +	CP15_AUXILIARY_FEATURE_0, +	CP15_C1_C0, +	CP15_CONTROL = CP15_C1_C0, +	CP15_AUXILIARY_CONTROL, +	CP15_COPROCESSOR_ACCESS_CONTROL, +	CP15_C2, +	CP15_C2_C0 = CP15_C2, +	CP15_TRANSLATION_BASE = CP15_C2_C0, +	CP15_TRANSLATION_BASE_TABLE_0 = CP15_TRANSLATION_BASE, +	CP15_TRANSLATION_BASE_TABLE_1, +	CP15_TRANSLATION_BASE_CONTROL, +	CP15_DOMAIN_ACCESS_CONTROL, +	CP15_RESERVED, +	/* Fault status */ +	CP15_FAULT_STATUS, +	CP15_INSTR_FAULT_STATUS, +	CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS, +	CP15_INST_FSR, +	/* Fault Address register */ +	CP15_FAULT_ADDRESS, +	CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS, +	CP15_WFAR, +	CP15_IFAR, +	CP15_PID, +	CP15_CONTEXT_ID, +	CP15_THREAD_URO, +	CP15_TLB_FAULT_ADDR, /* defined by SkyEye */ +	CP15_TLB_FAULT_STATUS, /* defined by SkyEye */ +	/* VFP registers */ +	VFP_BASE, +	VFP_FPSID = VFP_BASE, +	VFP_FPSCR, +	VFP_FPEXC, +#endif	 +	MAX_REG_NUM, +}; + +#define VFP_OFFSET(x) (x - VFP_BASE) +#endif diff --git a/src/core/src/arm/armcpu.h b/src/core/src/arm/armcpu.h new file mode 100644 index 000000000..ee4a860dd --- /dev/null +++ b/src/core/src/arm/armcpu.h @@ -0,0 +1,83 @@ +/* + *	arm + *	armcpu.h + * + *	Copyright (C) 2003, 2004 Sebastian Biallas (sb@biallas.net) + * + *	This program is free software; you can redistribute it and/or modify + *	it under the terms of the GNU General Public License version 2 as + *	published by the Free Software Foundation. + * + *	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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ARM_CPU_H__ +#define __ARM_CPU_H__ +//#include <skyeye_thread.h> +//#include <skyeye_obj.h> +//#include <skyeye_mach.h> +//#include <skyeye_exec.h> + +#include <stddef.h> +#include <stdio.h> + +#include "thread.h" + + +typedef struct ARM_CPU_State_s { +	ARMul_State * core; +	uint32_t core_num; +	/* The core id that boot from +	 */ +	uint32_t boot_core_id; +}ARM_CPU_State; + +//static ARM_CPU_State* get_current_cpu(){ +//	machine_config_t* mach = get_current_mach(); +//	/* Casting a conf_obj_t to ARM_CPU_State type */ +//	ARM_CPU_State* cpu = (ARM_CPU_State*)mach->cpu_data->obj; +// +//	return cpu; +//} + +/** +* @brief Get the core instance boot from +* +* @return +*/ +//static ARMul_State* get_boot_core(){ +//	ARM_CPU_State* cpu = get_current_cpu(); +//	return &cpu->core[cpu->boot_core_id]; +//} +/** +* @brief Get the instance of running core +* +* @return the core instance +*/ +//static ARMul_State* get_current_core(){ +//	/* Casting a conf_obj_t to ARM_CPU_State type */ +//	int id = Common::CurrentThreadId(); +//	/* If thread is not in running mode, we should give the boot core */ +//	if(get_thread_state(id) != Running_state){ +//		return get_boot_core(); +//	} +//	/* Judge if we are running in paralell or sequenial */ +//	if(thread_exist(id)){ +//		conf_object_t* conf_obj = get_current_exec_priv(id); +//		return (ARMul_State*)get_cast_conf_obj(conf_obj, "arm_core_t"); +//	} +// +//	return NULL; +//} + +#define CURRENT_CORE get_current_core() + +#endif + diff --git a/src/core/src/arm/armdefs.h b/src/core/src/arm/armdefs.h new file mode 100644 index 000000000..a0cf28a92 --- /dev/null +++ b/src/core/src/arm/armdefs.h @@ -0,0 +1,930 @@ +/*  armdefs.h -- ARMulator common definitions:  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. */ + +#ifndef _ARMDEFS_H_ +#define _ARMDEFS_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +//teawater add for arm2x86 2005.02.14------------------------------------------- +// koodailar remove it for mingw 2005.12.18---------------- +//anthonylee modify it for portable 2007.01.30 +//#include "portable/mman.h" + +#include "arm_regformat.h" +#include "platform.h" +#include "skyeye_defs.h" + +//AJ2D-------------------------------------------------------------------------- + +//teawater add for arm2x86 2005.07.03------------------------------------------- + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#if EMU_PLATFORM == PLATFORM_LINUX +#include <unistd.h> +#endif +#include <errno.h> +#include <sys/stat.h> +#include <fcntl.h> + +//#include <memory_space.h> +//AJ2D-------------------------------------------------------------------------- +#if 0 +#if 0 +#define DIFF_STATE 1 +#define __FOLLOW_MODE__ 0 +#else +#define DIFF_STATE 0 +#define __FOLLOW_MODE__ 1 +#endif +#endif + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +#define LOW 0 +#define HIGH 1 +#define LOWHIGH 1 +#define HIGHLOW 2 + +#ifndef u8 +#define u8      unsigned char +#define u16     unsigned short +#define u32     unsigned int +#define u64     unsigned long long +#endif /*u8 */ + +//teawater add DBCT_TEST_SPEED 2005.10.04--------------------------------------- +#include <signal.h> + +#include "platform.h" + +#if EMU_PLATFORM == PLATFORM_LINUX +#include <sys/time.h> +#endif + +//#define DBCT_TEST_SPEED +#define DBCT_TEST_SPEED_SEC	10 +//AJ2D-------------------------------------------------------------------------- + +//teawater add compile switch for DBCT GDB RSP function 2005.10.21-------------- +//#define DBCT_GDBRSP +//AJ2D-------------------------------------------------------------------------- + +//#include <skyeye_defs.h> +//#include <skyeye_types.h> + +#define ARM_BYTE_TYPE 		0 +#define ARM_HALFWORD_TYPE 	1 +#define ARM_WORD_TYPE 		2 + +//the define of cachetype +#define NONCACHE  0 +#define DATACACHE  1 +#define INSTCACHE  2 + +#ifndef __STDC__ +typedef char *VoidStar; +#endif + +typedef unsigned long long ARMdword;	/* must be 64 bits wide */ +typedef unsigned int ARMword;	/* must be 32 bits wide */ +typedef unsigned char ARMbyte;	/* must be 8 bits wide */ +typedef unsigned short ARMhword;	/* must be 16 bits wide */ +typedef struct ARMul_State ARMul_State; +typedef struct ARMul_io ARMul_io; +typedef struct ARMul_Energy ARMul_Energy; + +//teawater add for arm2x86 2005.06.24------------------------------------------- +#include <stdint.h> +//AJ2D-------------------------------------------------------------------------- +/* +//chy 2005-05-11 +#ifndef __CYGWIN__ +//teawater add for arm2x86 2005.02.14------------------------------------------- +typedef unsigned char           uint8_t; +typedef unsigned short          uint16_t; +typedef unsigned int            u32; +#if defined (__x86_64__) +typedef unsigned long           uint64_t; +#else +typedef unsigned long long      uint64_t; +#endif +////AJ2D-------------------------------------------------------------------------- +#endif +*/ + +#include "armmmu.h" +//#include "lcd/skyeye_lcd.h" + + +//#include "skyeye.h" +//#include "skyeye_device.h" +//#include "net/skyeye_net.h" +//#include "skyeye_config.h" + + +typedef unsigned ARMul_CPInits (ARMul_State * state); +typedef unsigned ARMul_CPExits (ARMul_State * state); +typedef unsigned ARMul_LDCs (ARMul_State * state, unsigned type, +			     ARMword instr, ARMword value); +typedef unsigned ARMul_STCs (ARMul_State * state, unsigned type, +			     ARMword instr, ARMword * value); +typedef unsigned ARMul_MRCs (ARMul_State * state, unsigned type, +			     ARMword instr, ARMword * value); +typedef unsigned ARMul_MCRs (ARMul_State * state, unsigned type, +			     ARMword instr, ARMword value); +typedef unsigned ARMul_MRRCs (ARMul_State * state, unsigned type, +			     ARMword instr, ARMword * value1, ARMword * value2); +typedef unsigned ARMul_MCRRs (ARMul_State * state, unsigned type, +			     ARMword instr, ARMword value1, ARMword value2); +typedef unsigned ARMul_CDPs (ARMul_State * state, unsigned type, +			     ARMword instr); +typedef unsigned ARMul_CPReads (ARMul_State * state, unsigned reg, +				ARMword * value); +typedef unsigned ARMul_CPWrites (ARMul_State * state, unsigned reg, +				 ARMword value); + + +//added by ksh,2004-3-5 +struct ARMul_io +{ +	ARMword *instr;		//to display the current interrupt state +	ARMword *net_flag;	//to judge if network is enabled +	ARMword *net_int;	//netcard interrupt + +	//ywc,2004-04-01 +	ARMword *ts_int; +	ARMword *ts_is_enable; +	ARMword *ts_addr_begin; +	ARMword *ts_addr_end; +	ARMword *ts_buffer; +}; + +/* added by ksh,2004-11-26,some energy profiling */ +struct ARMul_Energy +{ +	int energy_prof;	/* <tktan>  BUG200103282109 : for energy profiling */ +	int enable_func_energy;	/* <tktan> BUG200105181702 */ +	char *func_energy; +	int func_display;	/* <tktan> BUG200103311509 : for function call display */ +	int func_disp_start;	/* <tktan> BUG200104191428 : to start func profiling */ +	char *start_func;	/* <tktan> BUG200104191428 */ + +	FILE *outfile;		/* <tktan> BUG200105201531 : direct console to file */ +	long long tcycle, pcycle; +	float t_energy; +	void *cur_task;		/* <tktan> BUG200103291737 */ +	long long t_mem_cycle, t_idle_cycle, t_uart_cycle; +	long long p_mem_cycle, p_idle_cycle, p_uart_cycle; +	long long p_io_update_tcycle; +	/*record CCCR,to get current core frequency */ +	ARMword cccr; +}; +#if 0 +#define MAX_BANK 8 +#define MAX_STR  1024 + +typedef struct mem_bank +{ +	ARMword (*read_byte) (ARMul_State * state, ARMword addr); +	void (*write_byte) (ARMul_State * state, ARMword addr, ARMword data); +	  ARMword (*read_halfword) (ARMul_State * state, ARMword addr); +	void (*write_halfword) (ARMul_State * state, ARMword addr, +				ARMword data); +	  ARMword (*read_word) (ARMul_State * state, ARMword addr); +	void (*write_word) (ARMul_State * state, ARMword addr, ARMword data); +	unsigned int addr, len; +	char filename[MAX_STR]; +	unsigned type;		//chy 2003-09-21: maybe io,ram,rom +} mem_bank_t; +typedef struct +{ +	int bank_num; +	int current_num;	/*current num of bank */ +	mem_bank_t mem_banks[MAX_BANK]; +} mem_config_t; +#endif +#define VFP_REG_NUM 64 +struct ARMul_State +{ +	ARMword Emulate;	/* to start and stop emulation */ +	unsigned EndCondition;	/* reason for stopping */ +	unsigned ErrorCode;	/* type of illegal instruction */ + +	/* Order of the following register should not be modified */ +	ARMword Reg[16];	/* the current register file */ +	ARMword Cpsr;		/* the current psr */ +	ARMword Spsr_copy; +	ARMword phys_pc; +	ARMword Reg_usr[2]; +	ARMword Reg_svc[2]; /* R13_SVC R14_SVC */ +	ARMword Reg_abort[2]; /* R13_ABORT R14_ABORT */ +	ARMword Reg_undef[2]; /* R13 UNDEF R14 UNDEF */ +	ARMword Reg_irq[2];   /* R13_IRQ R14_IRQ */ +	ARMword Reg_firq[7];  /* R8---R14 FIRQ */ +	ARMword Spsr[7];	/* the exception psr's */ +	ARMword Mode;		/* the current mode */ +	ARMword Bank;		/* the current register bank */ +	ARMword exclusive_tag; +	ARMword exclusive_state; +	ARMword exclusive_result; +	ARMword CP15[VFP_BASE - CP15_BASE]; +	ARMword VFP[3]; /* FPSID, FPSCR, and FPEXC */ +	/* VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31). +	   VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31), +		and only 32 singleword registers are accessible (S0-S31). */ +	ARMword ExtReg[VFP_REG_NUM]; +	/* ---- End of the ordered registers ---- */ +	 +	ARMword RegBank[7][16];	/* all the registers */ +	//chy:2003-08-19, used in arm xscale +	/* 40 bit accumulator.  We always keep this 64 bits wide, +	   and move only 40 bits out of it in an MRA insn.  */ +	ARMdword Accumulator; + +	ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags;	/* dummy flags for speed */ +        unsigned long long int icounter, debug_icounter, kernel_icounter; +        unsigned int shifter_carry_out; +        //ARMword translate_pc; + +	/* add armv6 flags dyf:2010-08-09 */ +	ARMword GEFlag, EFlag, AFlag, QFlags; +	//chy:2003-08-19, used in arm v5e|xscale +	ARMword SFlag; +#ifdef MODET +	ARMword TFlag;		/* Thumb state */ +#endif +	ARMword instr, pc, temp;	/* saved register state */ +	ARMword loaded, decoded;	/* saved pipeline state */ +	//chy 2006-04-12 for ICE breakpoint +	ARMword loaded_addr, decoded_addr;	/* saved pipeline state addr*/ +	unsigned int NumScycles, NumNcycles, NumIcycles, NumCcycles, NumFcycles;	/* emulated cycles used */ +	unsigned long long NumInstrs;	/* the number of instructions executed */ +	unsigned NextInstr; +	unsigned VectorCatch;	/* caught exception mask */ +	unsigned CallDebug;	/* set to call the debugger */ +	unsigned CanWatch;	/* set by memory interface if its willing to suffer the +				   overhead of checking for watchpoints on each memory +				   access */ +	unsigned int StopHandle; + +	char *CommandLine;	/* Command Line from ARMsd */ + +	ARMul_CPInits *CPInit[16];	/* coprocessor initialisers */ +	ARMul_CPExits *CPExit[16];	/* coprocessor finalisers */ +	ARMul_LDCs *LDC[16];	/* LDC instruction */ +	ARMul_STCs *STC[16];	/* STC instruction */ +	ARMul_MRCs *MRC[16];	/* MRC instruction */ +	ARMul_MCRs *MCR[16];	/* MCR instruction */ +	ARMul_MRRCs *MRRC[16];	/* MRRC instruction */ +	ARMul_MCRRs *MCRR[16];	/* MCRR instruction */ +	ARMul_CDPs *CDP[16];	/* CDP instruction */ +	ARMul_CPReads *CPRead[16];	/* Read CP register */ +	ARMul_CPWrites *CPWrite[16];	/* Write CP register */ +	unsigned char *CPData[16];	/* Coprocessor data */ +	unsigned char const *CPRegWords[16];	/* map of coprocessor register sizes */ + +	unsigned EventSet;	/* the number of events in the queue */ +	unsigned int Now;	/* time to the nearest cycle */ +	struct EventNode **EventPtr;	/* the event list */ + +	unsigned Debug;		/* show instructions as they are executed */ +	unsigned NresetSig;	/* reset the processor */ +	unsigned NfiqSig; +	unsigned NirqSig; + +	unsigned abortSig; +	unsigned NtransSig; +	unsigned bigendSig; +	unsigned prog32Sig; +	unsigned data32Sig; +	unsigned syscallSig; + +/* 2004-05-09 chy +---------------------------------------------------------- +read ARM Architecture Reference Manual +2.6.5 Data Abort +There are three Abort Model in ARM arch. + +Early Abort Model: used in some ARMv3 and earlier implementations. In this +model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and +the base register was unchanged for all other instructions. (oldest) + +Base Restored Abort Model: If a Data Abort occurs in an instruction which +specifies base register writeback, the value in the base register is +unchanged. (strongarm, xscale) + +Base Updated Abort Model: If a Data Abort occurs in an instruction which +specifies base register writeback, the base register writeback still occurs. +(arm720T) + +read PART B +chap2 The System Control Coprocessor  CP15 +2.4 Register1:control register +L(bit 6): in some ARMv3 and earlier implementations, the abort model of the +processor could be configured: +0=early Abort Model Selected(now obsolete) +1=Late Abort Model selceted(same as Base Updated Abort Model) + +on later processors, this bit reads as 1 and ignores writes. +------------------------------------------------------------- +So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model) +    if lateabtSig=0, then it means Base Restored Abort Model +*/ +	unsigned lateabtSig; + +	ARMword Vector;		/* synthesize aborts in cycle modes */ +	ARMword Aborted;	/* sticky flag for aborts */ +	ARMword Reseted;	/* sticky flag for Reset */ +	ARMword Inted, LastInted;	/* sticky flags for interrupts */ +	ARMword Base;		/* extra hand for base writeback */ +	ARMword AbortAddr;	/* to keep track of Prefetch aborts */ + +	const struct Dbg_HostosInterface *hostif; + +	int verbose;		/* non-zero means print various messages like the banner */ + +	mmu_state_t mmu; +	int mmu_inited; +	//mem_state_t mem; +	/*remove io_state to skyeye_mach_*.c files */ +	//io_state_t io; +	/* point to a interrupt pending register. now for skyeye-ne2k.c +	 * later should move somewhere. e.g machine_config_t*/ + + +	//chy: 2003-08-11, for different arm core type +	unsigned is_v4;		/* Are we emulating a v4 architecture (or higher) ?  */ +	unsigned is_v5;		/* Are we emulating a v5 architecture ?  */ +	unsigned is_v5e;	/* Are we emulating a v5e architecture ?  */ +	unsigned is_v6;		/* Are we emulating a v6 architecture ?  */ +	unsigned is_v7;		/* Are we emulating a v7 architecture ?  */ +	unsigned is_XScale;	/* Are we emulating an XScale architecture ?  */ +	unsigned is_iWMMXt;	/* Are we emulating an iWMMXt co-processor ?  */ +	unsigned is_ep9312;	/* Are we emulating a Cirrus Maverick co-processor ?  */ +	//chy 2005-09-19 +	unsigned is_pxa27x;	/* Are we emulating a Intel PXA27x co-processor ?  */ +	//chy: seems only used in xscale's CP14 +	unsigned int LastTime;	/* Value of last call to ARMul_Time() */ +	ARMword CP14R0_CCD;	/* used to count 64 clock cycles with CP14 R0 bit 3 set */ + + +//added by ksh:for handle different machs io 2004-3-5 +	ARMul_io mach_io; + +/*added by ksh,2004-11-26,some energy profiling*/ +	ARMul_Energy energy; + +//teawater add for next_dis 2004.10.27----------------------- +	int disassemble; +//AJ2D------------------------------------------ + +//teawater add for arm2x86 2005.02.15------------------------------------------- +	u32 trap; +	u32 tea_break_addr; +	u32 tea_break_ok; +	int tea_pc; +//AJ2D-------------------------------------------------------------------------- +//teawater add for arm2x86 2005.07.03------------------------------------------- + +	/* +	 * 2007-01-24 removed the term-io functions by Anthony Lee, +	 * moved to "device/uart/skyeye_uart_stdio.c". +	 */ + +//AJ2D-------------------------------------------------------------------------- +//teawater add for arm2x86 2005.07.05------------------------------------------- +	//arm_arm A2-18 +	int abort_model;	//0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model  +//AJ2D-------------------------------------------------------------------------- +//teawater change for return if running tb dirty 2005.07.09--------------------- +	void *tb_now; +//AJ2D-------------------------------------------------------------------------- + +//teawater add for record reg value to ./reg.txt 2005.07.10--------------------- +	FILE *tea_reg_fd; +//AJ2D-------------------------------------------------------------------------- + +/*added by ksh in 2005-10-1*/ +	cpu_config_t *cpu; +	//mem_config_t *mem_bank; + +/* added LPC remap function */ +	int vector_remap_flag; +	u32 vector_remap_addr; +	u32 vector_remap_size; + +	u32 step; +	u32 cycle; +	int stop_simulator; +	conf_object_t *dyncom_cpu; +//teawater add DBCT_TEST_SPEED 2005.10.04--------------------------------------- +#ifdef DBCT_TEST_SPEED +	uint64_t	instr_count; +#endif	//DBCT_TEST_SPEED +//	FILE * state_log; +//diff log +//#if DIFF_STATE +	FILE * state_log; +//#endif +	/* monitored memory for exclusice access */ +	ARMword exclusive_tag_array[128]; +	/* 1 means exclusive access and 0 means open access */ +	ARMword exclusive_access_state; + +	memory_space_intf space;	 +	u32 CurrInstr; +	u32 last_pc; /* the last pc executed */ +	u32 last_instr; /* the last inst executed */ +	u32 WriteAddr[17]; +	u32 WriteData[17]; +	u32 WritePc[17]; +	u32 CurrWrite; +}; +#define DIFF_WRITE 0 + +typedef ARMul_State arm_core_t; +#define ResetPin NresetSig +#define FIQPin NfiqSig +#define IRQPin NirqSig +#define AbortPin abortSig +#define TransPin NtransSig +#define BigEndPin bigendSig +#define Prog32Pin prog32Sig +#define Data32Pin data32Sig +#define LateAbortPin lateabtSig + +/***************************************************************************\ +*                        Types of ARM we know about                         * +\***************************************************************************/ + +/* The bitflags */ +#define ARM_Fix26_Prop   0x01 +#define ARM_Nexec_Prop   0x02 +#define ARM_Debug_Prop   0x10 +#define ARM_Isync_Prop   ARM_Debug_Prop +#define ARM_Lock_Prop    0x20 +//chy 2003-08-11  +#define ARM_v4_Prop      0x40 +#define ARM_v5_Prop      0x80 +/*jeff.du 2010-08-05 */ +#define ARM_v6_Prop      0xc0 + +#define ARM_v5e_Prop     0x100 +#define ARM_XScale_Prop  0x200 +#define ARM_ep9312_Prop  0x400 +#define ARM_iWMMXt_Prop  0x800 +//chy 2005-09-19 +#define ARM_PXA27X_Prop  0x1000 +#define ARM_v7_Prop      0x2000 + +/* ARM2 family */ +#define ARM2    (ARM_Fix26_Prop) +#define ARM2as  ARM2 +#define ARM61   ARM2 +#define ARM3    ARM2 + +#ifdef ARM60			/* previous definition in armopts.h */ +#undef ARM60 +#endif + +/* ARM6 family */ +#define ARM6    (ARM_Lock_Prop) +#define ARM60   ARM6 +#define ARM600  ARM6 +#define ARM610  ARM6 +#define ARM620  ARM6 + + +/***************************************************************************\ +*                   Macros to extract instruction fields                    * +\***************************************************************************/ + +#define BIT(n) ( (ARMword)(instr>>(n))&1)	/* bit n of instruction */ +#define BITS(m,n) ( (ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) )	/* bits m to n of instr */ +#define TOPBITS(n) (instr >> (n))	/* bits 31 to n of instr */ + +/***************************************************************************\ +*                      The hardware vector addresses                        * +\***************************************************************************/ + +#define ARMResetV 0L +#define ARMUndefinedInstrV 4L +#define ARMSWIV 8L +#define ARMPrefetchAbortV 12L +#define ARMDataAbortV 16L +#define ARMAddrExceptnV 20L +#define ARMIRQV 24L +#define ARMFIQV 28L +#define ARMErrorV 32L		/* This is an offset, not an address ! */ + +#define ARMul_ResetV ARMResetV +#define ARMul_UndefinedInstrV ARMUndefinedInstrV +#define ARMul_SWIV ARMSWIV +#define ARMul_PrefetchAbortV ARMPrefetchAbortV +#define ARMul_DataAbortV ARMDataAbortV +#define ARMul_AddrExceptnV ARMAddrExceptnV +#define ARMul_IRQV ARMIRQV +#define ARMul_FIQV ARMFIQV + +/***************************************************************************\ +*                          Mode and Bank Constants                          * +\***************************************************************************/ + +#define USER26MODE 0L +#define FIQ26MODE 1L +#define IRQ26MODE 2L +#define SVC26MODE 3L +#define USER32MODE 16L +#define FIQ32MODE 17L +#define IRQ32MODE 18L +#define SVC32MODE 19L +#define ABORT32MODE 23L +#define UNDEF32MODE 27L +//chy 2006-02-15 add system32 mode +#define SYSTEM32MODE 31L + +#define ARM32BITMODE (state->Mode > 3) +#define ARM26BITMODE (state->Mode <= 3) +#define ARMMODE (state->Mode) +#define ARMul_MODEBITS 0x1fL +#define ARMul_MODE32BIT ARM32BITMODE +#define ARMul_MODE26BIT ARM26BITMODE + +#define USERBANK 0 +#define FIQBANK 1 +#define IRQBANK 2 +#define SVCBANK 3 +#define ABORTBANK 4 +#define UNDEFBANK 5 +#define DUMMYBANK 6 +#define SYSTEMBANK USERBANK +#define BANK_CAN_ACCESS_SPSR(bank)  \ +  ((bank) != USERBANK && (bank) != SYSTEMBANK && (bank) != DUMMYBANK) + + +/***************************************************************************\ +*                  Definitons of things in the emulator                     * +\***************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif +extern void ARMul_EmulateInit (void); +extern void ARMul_Reset (ARMul_State * state); +#ifdef __cplusplus +	} +#endif +extern ARMul_State *ARMul_NewState (ARMul_State * state); +extern ARMword ARMul_DoProg (ARMul_State * state); +extern ARMword ARMul_DoInstr (ARMul_State * state); +/***************************************************************************\ +*                Definitons of things for event handling                    * +\***************************************************************************/ + +extern void ARMul_ScheduleEvent (ARMul_State * state, unsigned int delay, +				 unsigned (*func) ()); +extern void ARMul_EnvokeEvent (ARMul_State * state); +extern unsigned int ARMul_Time (ARMul_State * state); + +/***************************************************************************\ +*                          Useful support routines                          * +\***************************************************************************/ + +extern ARMword ARMul_GetReg (ARMul_State * state, unsigned mode, +			     unsigned reg); +extern void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, +			  ARMword value); +extern ARMword ARMul_GetPC (ARMul_State * state); +extern ARMword ARMul_GetNextPC (ARMul_State * state); +extern void ARMul_SetPC (ARMul_State * state, ARMword value); +extern ARMword ARMul_GetR15 (ARMul_State * state); +extern void ARMul_SetR15 (ARMul_State * state, ARMword value); + +extern ARMword ARMul_GetCPSR (ARMul_State * state); +extern void ARMul_SetCPSR (ARMul_State * state, ARMword value); +extern ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode); +extern void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value); + +/***************************************************************************\ +*                  Definitons of things to handle aborts                    * +\***************************************************************************/ + +extern void ARMul_Abort (ARMul_State * state, ARMword address); +#ifdef MODET +#define ARMul_ABORTWORD (state->TFlag ? 0xefffdfff : 0xefffffff)	/* SWI -1 */ +#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \ +                                        state->AbortAddr = (address & (state->TFlag ? ~1L : ~3L)) +#else +#define ARMul_ABORTWORD 0xefffffff	/* SWI -1 */ +#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \ +                                        state->AbortAddr = (address & ~3L) +#endif +#define ARMul_DATAABORT(address) state->abortSig = HIGH ; \ +                                 state->Aborted = ARMul_DataAbortV ; +#define ARMul_CLEARABORT state->abortSig = LOW + +/***************************************************************************\ +*              Definitons of things in the memory interface                 * +\***************************************************************************/ + +extern unsigned ARMul_MemoryInit (ARMul_State * state, +				  unsigned int initmemsize); +extern void ARMul_MemoryExit (ARMul_State * state); + +extern ARMword ARMul_LoadInstrS (ARMul_State * state, ARMword address, +				 ARMword isize); +extern ARMword ARMul_LoadInstrN (ARMul_State * state, ARMword address, +				 ARMword isize); +#ifdef __cplusplus +extern "C" { +#endif +extern ARMword ARMul_ReLoadInstr (ARMul_State * state, ARMword address, +				  ARMword isize); +#ifdef __cplusplus +	} +#endif +extern ARMword ARMul_LoadWordS (ARMul_State * state, ARMword address); +extern ARMword ARMul_LoadWordN (ARMul_State * state, ARMword address); +extern ARMword ARMul_LoadHalfWord (ARMul_State * state, ARMword address); +extern ARMword ARMul_LoadByte (ARMul_State * state, ARMword address); + +extern void ARMul_StoreWordS (ARMul_State * state, ARMword address, +			      ARMword data); +extern void ARMul_StoreWordN (ARMul_State * state, ARMword address, +			      ARMword data); +extern void ARMul_StoreHalfWord (ARMul_State * state, ARMword address, +				 ARMword data); +extern void ARMul_StoreByte (ARMul_State * state, ARMword address, +			     ARMword data); + +extern ARMword ARMul_SwapWord (ARMul_State * state, ARMword address, +			       ARMword data); +extern ARMword ARMul_SwapByte (ARMul_State * state, ARMword address, +			       ARMword data); + +extern void ARMul_Icycles (ARMul_State * state, unsigned number, +			   ARMword address); +extern void ARMul_Ccycles (ARMul_State * state, unsigned number, +			   ARMword address); + +extern ARMword ARMul_ReadWord (ARMul_State * state, ARMword address); +extern ARMword ARMul_ReadByte (ARMul_State * state, ARMword address); +extern void ARMul_WriteWord (ARMul_State * state, ARMword address, +			     ARMword data); +extern void ARMul_WriteByte (ARMul_State * state, ARMword address, +			     ARMword data); + +extern ARMword ARMul_MemAccess (ARMul_State * state, ARMword, ARMword, +				ARMword, ARMword, ARMword, ARMword, ARMword, +				ARMword, ARMword, ARMword); + +/***************************************************************************\ +*            Definitons of things in the co-processor interface             * +\***************************************************************************/ + +#define ARMul_FIRST 0 +#define ARMul_TRANSFER 1 +#define ARMul_BUSY 2 +#define ARMul_DATA 3 +#define ARMul_INTERRUPT 4 +#define ARMul_DONE 0 +#define ARMul_CANT 1 +#define ARMul_INC 3 + +#define ARMul_CP13_R0_FIQ       0x1 +#define ARMul_CP13_R0_IRQ       0x2 +#define ARMul_CP13_R8_PMUS      0x1 + +#define ARMul_CP14_R0_ENABLE    0x0001 +#define ARMul_CP14_R0_CLKRST    0x0004 +#define ARMul_CP14_R0_CCD       0x0008 +#define ARMul_CP14_R0_INTEN0    0x0010 +#define ARMul_CP14_R0_INTEN1    0x0020 +#define ARMul_CP14_R0_INTEN2    0x0040 +#define ARMul_CP14_R0_FLAG0     0x0100 +#define ARMul_CP14_R0_FLAG1     0x0200 +#define ARMul_CP14_R0_FLAG2     0x0400 +#define ARMul_CP14_R10_MOE_IB   0x0004 +#define ARMul_CP14_R10_MOE_DB   0x0008 +#define ARMul_CP14_R10_MOE_BT   0x000c +#define ARMul_CP15_R1_ENDIAN    0x0080 +#define ARMul_CP15_R1_ALIGN     0x0002 +#define ARMul_CP15_R5_X         0x0400 +#define ARMul_CP15_R5_ST_ALIGN  0x0001 +#define ARMul_CP15_R5_IMPRE     0x0406 +#define ARMul_CP15_R5_MMU_EXCPT 0x0400 +#define ARMul_CP15_DBCON_M      0x0100 +#define ARMul_CP15_DBCON_E1     0x000c +#define ARMul_CP15_DBCON_E0     0x0003 + +extern unsigned ARMul_CoProInit (ARMul_State * state); +extern void ARMul_CoProExit (ARMul_State * state); +extern void ARMul_CoProAttach (ARMul_State * state, unsigned number, +			       ARMul_CPInits * init, ARMul_CPExits * exit, +			       ARMul_LDCs * ldc, ARMul_STCs * stc, +			       ARMul_MRCs * mrc, ARMul_MCRs * mcr, +			       ARMul_MRRCs * mrrc, ARMul_MCRRs * mcrr, +			       ARMul_CDPs * cdp, +			       ARMul_CPReads * read, ARMul_CPWrites * write); +extern void ARMul_CoProDetach (ARMul_State * state, unsigned number); + +/***************************************************************************\ +*               Definitons of things in the host environment                * +\***************************************************************************/ + +extern unsigned ARMul_OSInit (ARMul_State * state); +extern void ARMul_OSExit (ARMul_State * state); + +#ifdef __cplusplus + extern "C" { +#endif + +extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number); +#ifdef __cplusplus +} +#endif + + +extern ARMword ARMul_OSLastErrorP (ARMul_State * state); + +extern ARMword ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr); +extern unsigned ARMul_OSException (ARMul_State * state, ARMword vector, +				   ARMword pc); +extern int rdi_log; + +/***************************************************************************\ +*                            Host-dependent stuff                           * +\***************************************************************************/ + +#ifdef macintosh +pascal void SpinCursor (short increment);	/* copied from CursorCtl.h */ +# define HOURGLASS           SpinCursor( 1 ) +# define HOURGLASS_RATE      1023	/* 2^n - 1 */ +#endif + +//teawater add for arm2x86 2005.02.14------------------------------------------- +/*ywc 2005-03-31*/ +/* +#include "arm2x86.h" +#include "arm2x86_dp.h" +#include "arm2x86_movl.h" +#include "arm2x86_psr.h" +#include "arm2x86_shift.h" +#include "arm2x86_mem.h" +#include "arm2x86_mul.h" +#include "arm2x86_test.h" +#include "arm2x86_other.h" +#include "list.h" +#include "tb.h" +*/ +#define EQ 0 +#define NE 1 +#define CS 2 +#define CC 3 +#define MI 4 +#define PL 5 +#define VS 6 +#define VC 7 +#define HI 8 +#define LS 9 +#define GE 10 +#define LT 11 +#define GT 12 +#define LE 13 +#define AL 14 +#define NV 15 + +#ifndef NFLAG +#define NFLAG	state->NFlag +#endif //NFLAG + +#ifndef ZFLAG +#define ZFLAG	state->ZFlag +#endif //ZFLAG + +#ifndef CFLAG +#define CFLAG	state->CFlag +#endif //CFLAG + +#ifndef VFLAG +#define VFLAG	state->VFlag +#endif //VFLAG + +#ifndef IFLAG +#define IFLAG	(state->IFFlags >> 1) +#endif //IFLAG + +#ifndef FFLAG +#define FFLAG	(state->IFFlags & 1) +#endif //FFLAG + +#ifndef IFFLAGS +#define IFFLAGS	state->IFFlags +#endif //VFLAG + +#define FLAG_MASK	0xf0000000 +#define NBIT_SHIFT	31 +#define ZBIT_SHIFT	30 +#define CBIT_SHIFT	29 +#define VBIT_SHIFT	28 +#ifdef DBCT +//teawater change for local tb branch directly jump 2005.10.18------------------ +#include "dbct/list.h" +#include "dbct/arm2x86.h" +#include "dbct/arm2x86_dp.h" +#include "dbct/arm2x86_movl.h" +#include "dbct/arm2x86_psr.h" +#include "dbct/arm2x86_shift.h" +#include "dbct/arm2x86_mem.h" +#include "dbct/arm2x86_mul.h" +#include "dbct/arm2x86_test.h" +#include "dbct/arm2x86_other.h" +#include "dbct/arm2x86_coproc.h" +#include "dbct/tb.h" +#endif +//AJ2D-------------------------------------------------------------------------- +//AJ2D-------------------------------------------------------------------------- +#define SKYEYE_OUTREGS(fd) { fprintf ((fd), "R %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,C %x,S %x,%x,%x,%x,%x,%x,%x,M %x,B %x,E %x,I %x,P %x,T %x,L %x,D %x,",\ +                         state->Reg[0],state->Reg[1],state->Reg[2],state->Reg[3], \ +                         state->Reg[4],state->Reg[5],state->Reg[6],state->Reg[7], \ +                         state->Reg[8],state->Reg[9],state->Reg[10],state->Reg[11], \ +                         state->Reg[12],state->Reg[13],state->Reg[14],state->Reg[15], \ +			 state->Cpsr,   state->Spsr[0], state->Spsr[1], state->Spsr[2],\ +                         state->Spsr[3],state->Spsr[4], state->Spsr[5], state->Spsr[6],\ +			 state->Mode,state->Bank,state->ErrorCode,state->instr,state->pc,\ +			 state->temp,state->loaded,state->decoded);} + +#define SKYEYE_OUTMOREREGS(fd) { fprintf ((fd),"\ +RUs %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\ +RF  %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\ +RI  %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\ +RS  %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\ +RA  %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\ +RUn %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",\ +                         state->RegBank[0][0],state->RegBank[0][1],state->RegBank[0][2],state->RegBank[0][3], \ +                         state->RegBank[0][4],state->RegBank[0][5],state->RegBank[0][6],state->RegBank[0][7], \ +                         state->RegBank[0][8],state->RegBank[0][9],state->RegBank[0][10],state->RegBank[0][11], \ +                         state->RegBank[0][12],state->RegBank[0][13],state->RegBank[0][14],state->RegBank[0][15], \ +                         state->RegBank[1][0],state->RegBank[1][1],state->RegBank[1][2],state->RegBank[1][3], \ +                         state->RegBank[1][4],state->RegBank[1][5],state->RegBank[1][6],state->RegBank[1][7], \ +                         state->RegBank[1][8],state->RegBank[1][9],state->RegBank[1][10],state->RegBank[1][11], \ +                         state->RegBank[1][12],state->RegBank[1][13],state->RegBank[1][14],state->RegBank[1][15], \ +                         state->RegBank[2][0],state->RegBank[2][1],state->RegBank[2][2],state->RegBank[2][3], \ +                         state->RegBank[2][4],state->RegBank[2][5],state->RegBank[2][6],state->RegBank[2][7], \ +                         state->RegBank[2][8],state->RegBank[2][9],state->RegBank[2][10],state->RegBank[2][11], \ +                         state->RegBank[2][12],state->RegBank[2][13],state->RegBank[2][14],state->RegBank[2][15], \ +                         state->RegBank[3][0],state->RegBank[3][1],state->RegBank[3][2],state->RegBank[3][3], \ +                         state->RegBank[3][4],state->RegBank[3][5],state->RegBank[3][6],state->RegBank[3][7], \ +                         state->RegBank[3][8],state->RegBank[3][9],state->RegBank[3][10],state->RegBank[3][11], \ +                         state->RegBank[3][12],state->RegBank[3][13],state->RegBank[3][14],state->RegBank[3][15], \ +                         state->RegBank[4][0],state->RegBank[4][1],state->RegBank[4][2],state->RegBank[4][3], \ +                         state->RegBank[4][4],state->RegBank[4][5],state->RegBank[4][6],state->RegBank[4][7], \ +                         state->RegBank[4][8],state->RegBank[4][9],state->RegBank[4][10],state->RegBank[4][11], \ +                         state->RegBank[4][12],state->RegBank[4][13],state->RegBank[4][14],state->RegBank[4][15], \ +                         state->RegBank[5][0],state->RegBank[5][1],state->RegBank[5][2],state->RegBank[5][3], \ +                         state->RegBank[5][4],state->RegBank[5][5],state->RegBank[5][6],state->RegBank[5][7], \ +                         state->RegBank[5][8],state->RegBank[5][9],state->RegBank[5][10],state->RegBank[5][11], \ +                         state->RegBank[5][12],state->RegBank[5][13],state->RegBank[5][14],state->RegBank[5][15] \ +		);} + + +#define SA1110        0x6901b110 +#define SA1100        0x4401a100 +#define PXA250	      0x69052100 +#define PXA270 	      0x69054110 +//#define PXA250              0x69052903 +// 0x69052903;  //PXA250 B1 from intel 278522-001.pdf + + +extern void ARMul_UndefInstr (ARMul_State *, ARMword); +extern void ARMul_FixCPSR (ARMul_State *, ARMword, ARMword); +extern void ARMul_FixSPSR (ARMul_State *, ARMword, ARMword); +extern void ARMul_ConsolePrint (ARMul_State *, const char *, ...); +extern void ARMul_SelectProcessor (ARMul_State *, unsigned); + +#define DIFF_LOG 0 +#define SAVE_LOG 0 + +#endif /* _ARMDEFS_H_ */ diff --git a/src/core/src/arm/armemu.cpp b/src/core/src/arm/armemu.cpp new file mode 100644 index 000000000..e5c287236 --- /dev/null +++ b/src/core/src/arm/armemu.cpp @@ -0,0 +1,6618 @@ +/*  armemu.c -- Main instruction emulation:  ARM7 Instruction Emulator. +    Copyright (C) 1994 Advanced RISC Machines Ltd. +    Modifications to add arch. v4 support by <jsmith@cygnus.com>. +  +    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 "arm_regformat.h" +#include "armdefs.h" +#include "armemu.h" +#include "armos.h" + +//#include "skyeye_callback.h" +//#include "skyeye_bus.h" +//#include "sim_control.h" +//#include "skyeye_pref.h" +//#include "skyeye.h" +//#include "skyeye2gdb.h" +//#include "code_cov.h" + +//#include "iwmmxt.h" +//chy 2003-07-11: for debug instrs +//extern int skyeye_instr_debug; +extern FILE *skyeye_logfd; + +static ARMword GetDPRegRHS (ARMul_State *, ARMword); +static ARMword GetDPSRegRHS (ARMul_State *, ARMword); +static void WriteR15 (ARMul_State *, ARMword); +static void WriteSR15 (ARMul_State *, ARMword); +static void WriteR15Branch (ARMul_State *, ARMword); +static ARMword GetLSRegRHS (ARMul_State *, ARMword); +static ARMword GetLS7RHS (ARMul_State *, ARMword); +static unsigned LoadWord (ARMul_State *, ARMword, ARMword); +static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int); +static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int); +static unsigned StoreWord (ARMul_State *, ARMword, ARMword); +static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword); +static unsigned StoreByte (ARMul_State *, ARMword, ARMword); +static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword); +static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword); +static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword); +static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword); +static unsigned Multiply64 (ARMul_State *, ARMword, int, int); +static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int); +static void Handle_Load_Double (ARMul_State *, ARMword); +static void Handle_Store_Double (ARMul_State *, ARMword); +void +XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far); +int              +XScale_debug_moe (ARMul_State * state, int moe); +unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, +                                        unsigned cpnum); + +static int +handle_v6_insn (ARMul_State * state, ARMword instr); + +#define LUNSIGNED (0)		/* unsigned operation */ +#define LSIGNED   (1)		/* signed operation */ +#define LDEFAULT  (0)		/* default : do nothing */ +#define LSCC      (1)		/* set condition codes on result */ + +#ifdef NEED_UI_LOOP_HOOK +/* How often to run the ui_loop update, when in use.  */ +#define UI_LOOP_POLL_INTERVAL 0x32000 + +/* Counter for the ui_loop_hook update.  */ +static int ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL; + +/* Actual hook to call to run through gdb's gui event loop.  */ +extern int (*ui_loop_hook) (int); +#endif /* NEED_UI_LOOP_HOOK */ + +/* Short-hand macros for LDR/STR.  */ + +/* Store post decrement writeback.  */ +#define SHDOWNWB()                                      \ +  lhs = LHS ;                                           \ +  if (StoreHalfWord (state, instr, lhs))                \ +     LSBase = lhs - GetLS7RHS (state, instr); + +/* Store post increment writeback.  */ +#define SHUPWB()                                        \ +  lhs = LHS ;                                           \ +  if (StoreHalfWord (state, instr, lhs))                \ +     LSBase = lhs + GetLS7RHS (state, instr); + +/* Store pre decrement.  */ +#define SHPREDOWN()                                     \ +  (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr)); + +/* Store pre decrement writeback.  */ +#define SHPREDOWNWB()                                   \ +  temp = LHS - GetLS7RHS (state, instr);                \ +  if (StoreHalfWord (state, instr, temp))               \ +     LSBase = temp; + +/* Store pre increment.  */ +#define SHPREUP()                                       \ +  (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr)); + +/* Store pre increment writeback.  */ +#define SHPREUPWB()                                     \ +  temp = LHS + GetLS7RHS (state, instr);                \ +  if (StoreHalfWord (state, instr, temp))               \ +     LSBase = temp; + +/* Load post decrement writeback.  */ +#define LHPOSTDOWN()                                    \ +{                                                       \ +  int done = 1;                                        	\ +  lhs = LHS;						\ +  temp = lhs - GetLS7RHS (state, instr);		\ +  							\ +  switch (BITS (5, 6))					\ +    {                                  			\ +    case 1: /* H */                                     \ +      if (LoadHalfWord (state, instr, lhs, LUNSIGNED))  \ +         LSBase = temp;        				\ +      break;                                           	\ +    case 2: /* SB */                                    \ +      if (LoadByte (state, instr, lhs, LSIGNED))        \ +         LSBase = temp;        				\ +      break;                                           	\ +    case 3: /* SH */                                    \ +      if (LoadHalfWord (state, instr, lhs, LSIGNED))    \ +         LSBase = temp;        				\ +      break;                                           	\ +    case 0: /* SWP handled elsewhere.  */               \ +    default:                                            \ +      done = 0;                                        	\ +      break;                                           	\ +    }                                                   \ +  if (done)                                             \ +     break;                                            	\ +} + +/* Load post increment writeback.  */ +#define LHPOSTUP()                                      \ +{                                                       \ +  int done = 1;                                        	\ +  lhs = LHS;                                           	\ +  temp = lhs + GetLS7RHS (state, instr);		\ +  							\ +  switch (BITS (5, 6))					\ +    {                                  			\ +    case 1: /* H */                                     \ +      if (LoadHalfWord (state, instr, lhs, LUNSIGNED))  \ +         LSBase = temp;        				\ +      break;                                           	\ +    case 2: /* SB */                                    \ +      if (LoadByte (state, instr, lhs, LSIGNED))        \ +         LSBase = temp;        				\ +      break;                                           	\ +    case 3: /* SH */                                    \ +      if (LoadHalfWord (state, instr, lhs, LSIGNED))    \ +         LSBase = temp;        				\ +      break;                                           	\ +    case 0: /* SWP handled elsewhere.  */               \ +    default:                                            \ +      done = 0;                                        	\ +      break;                                           	\ +    }                                                   \ +  if (done)                                             \ +     break;                                            	\ +} + +/* Load pre decrement.  */ +#define LHPREDOWN()                                     	\ +{                                                       	\ +  int done = 1;                                        		\ +								\ +  temp = LHS - GetLS7RHS (state, instr);                 	\ +  switch (BITS (5, 6))						\ +    {                                  				\ +    case 1: /* H */                                     	\ +      (void) LoadHalfWord (state, instr, temp, LUNSIGNED);  	\ +      break;                                           		\ +    case 2: /* SB */                                    	\ +      (void) LoadByte (state, instr, temp, LSIGNED);        	\ +      break;                                           		\ +    case 3: /* SH */                                    	\ +      (void) LoadHalfWord (state, instr, temp, LSIGNED);    	\ +      break;                                           		\ +    case 0:							\ +      /* SWP handled elsewhere.  */                 		\ +    default:                                            	\ +      done = 0;                                        		\ +      break;                                           		\ +    }                                                   	\ +  if (done)                                             	\ +     break;                                            		\ +} + +/* Load pre decrement writeback.  */ +#define LHPREDOWNWB()                                   	\ +{                                                       	\ +  int done = 1;                                        		\ +								\ +  temp = LHS - GetLS7RHS (state, instr);                	\ +  switch (BITS (5, 6))						\ +    {                                  				\ +    case 1: /* H */                                     	\ +      if (LoadHalfWord (state, instr, temp, LUNSIGNED))     	\ +         LSBase = temp;                                		\ +      break;                                           		\ +    case 2: /* SB */                                    	\ +      if (LoadByte (state, instr, temp, LSIGNED))           	\ +         LSBase = temp;                                		\ +      break;                                           		\ +    case 3: /* SH */                                    	\ +      if (LoadHalfWord (state, instr, temp, LSIGNED))       	\ +         LSBase = temp;                                		\ +      break;                                           		\ +    case 0:							\ +      /* SWP handled elsewhere.  */                 		\ +    default:                                            	\ +      done = 0;                                        		\ +      break;                                           		\ +    }                                                   	\ +  if (done)                                             	\ +     break;                                            		\ +} + +/* Load pre increment.  */ +#define LHPREUP()                                       	\ +{                                                       	\ +  int done = 1;                                        		\ +								\ +  temp = LHS + GetLS7RHS (state, instr);                 	\ +  switch (BITS (5, 6))						\ +    {                                  				\ +    case 1: /* H */                                     	\ +      (void) LoadHalfWord (state, instr, temp, LUNSIGNED);  	\ +      break;                                           		\ +    case 2: /* SB */                                    	\ +      (void) LoadByte (state, instr, temp, LSIGNED);        	\ +      break;                                           		\ +    case 3: /* SH */                                    	\ +      (void) LoadHalfWord (state, instr, temp, LSIGNED);    	\ +      break;                                           		\ +    case 0:							\ +      /* SWP handled elsewhere.  */                 		\ +    default:                                            	\ +      done = 0;                                        		\ +      break;                                           		\ +    }                                                   	\ +  if (done)                                             	\ +     break;                                            		\ +} + +/* Load pre increment writeback.  */ +#define LHPREUPWB()                                     	\ +{                                                       	\ +  int done = 1;                                        		\ +								\ +  temp = LHS + GetLS7RHS (state, instr);                	\ +  switch (BITS (5, 6))						\ +    {                                  				\ +    case 1: /* H */                                     	\ +      if (LoadHalfWord (state, instr, temp, LUNSIGNED))     	\ +	LSBase = temp;                                		\ +      break;                                           		\ +    case 2: /* SB */                                    	\ +      if (LoadByte (state, instr, temp, LSIGNED))           	\ +	LSBase = temp;                                		\ +      break;                                           		\ +    case 3: /* SH */                                    	\ +      if (LoadHalfWord (state, instr, temp, LSIGNED))       	\ +	LSBase = temp;                                		\ +      break;                                           		\ +    case 0:							\ +      /* SWP handled elsewhere.  */                 		\ +    default:                                            	\ +      done = 0;                                        		\ +      break;                                           		\ +    }                                                   	\ +  if (done)                                             	\ +     break;                                            		\ +} + +/*ywc 2005-03-31*/ +//teawater add for arm2x86 2005.02.17------------------------------------------- +#ifdef DBCT +#include "dbct/tb.h" +#include "dbct/arm2x86_self.h" +#endif +//AJ2D-------------------------------------------------------------------------- + +//Diff register +unsigned int mirror_register_file[39]; + +/* EMULATION of ARM6.  */ + +/* The PC pipeline value depends on whether ARM +   or Thumb instructions are being executed.  */ +ARMword isize; + +extern int debugmode; +int ARMul_ICE_debug(ARMul_State *state,ARMword instr,ARMword addr); +#ifdef MODE32 +//chy 2006-04-12, for ICE debug +int ARMul_ICE_debug(ARMul_State *state,ARMword instr,ARMword addr) +{ + int i; +#if 0 + if (debugmode) { +   if (instr == ARMul_ABORTWORD) return 0; +   for (i = 0; i < skyeye_ice.num_bps; i++) { +	 if (skyeye_ice.bps[i] == addr) { +		 //for test +		 //printf("SKYEYE: ICE_debug bps [%d]== 0x%x\n", i,addr); +		 state->EndCondition = 0; +		 state->Emulate = STOP; +		 return 1; +	 } +    } +    if (skyeye_ice.tps_status==TRACE_STARTED) +    { +	for (i = 0; i < skyeye_ice.num_tps; i++) +        { +            if (((skyeye_ice.tps[i].tp_address==addr)&&(skyeye_ice.tps[i].status==TRACEPOINT_ENABLED))||(skyeye_ice.tps[i].status==TRACEPOINT_STEPPING)) +            { +                handle_tracepoint(i); +            } +     } +    } + } +                /* do profiling for code coverage */ +                if (skyeye_config.code_cov.prof_on) +                        cov_prof(EXEC_FLAG, addr); +#endif +	/* chech if we need to run some callback functions at this time */ +	//generic_arch_t* arch_instance = get_arch_instance("");	 +	//exec_callback(Step_callback, arch_instance); +	//if (!SIM_is_running()) { +	//	if (instr == ARMul_ABORTWORD) return 0; +	//	state->EndCondition = 0; +	//	state->Emulate = STOP; +	//	return 1; +	//} +	return 0; +} + +/* +void chy_debug() +{ +	printf("SkyEye chy_deubeg begin\n"); +} +*/ +ARMword +ARMul_Emulate32 (ARMul_State * state) +#else +ARMword +ARMul_Emulate26 (ARMul_State * state) +#endif +{ +	ARMword instr;		/* The current instruction.  */ +	ARMword dest = 0;	/* Almost the DestBus.  */ +	ARMword temp;		/* Ubiquitous third hand.  */ +	ARMword pc = 0;		/* The address of the current instruction.  */ +	ARMword lhs;		/* Almost the ABus and BBus.  */ +	ARMword rhs; +	ARMword decoded = 0;	/* Instruction pipeline.  */ +	ARMword loaded = 0; +	ARMword decoded_addr=0; +	ARMword loaded_addr=0; +	ARMword have_bp=0; + +	/* shenoubang */ +	static int instr_sum = 0; +	int reg_index = 0; +#if DIFF_STATE +//initialize all mirror register for follow mode +	for (reg_index = 0; reg_index < 16; reg_index ++) { +			mirror_register_file[reg_index] = state->Reg[reg_index]; +	} +    mirror_register_file[CPSR_REG] = state->Cpsr; +    mirror_register_file[R13_SVC] = state->RegBank[SVCBANK][13]; +    mirror_register_file[R14_SVC] = state->RegBank[SVCBANK][14]; +    mirror_register_file[R13_ABORT] = state->RegBank[ABORTBANK][13]; +    mirror_register_file[R14_ABORT] = state->RegBank[ABORTBANK][14]; +    mirror_register_file[R13_UNDEF] = state->RegBank[UNDEFBANK][13]; +    mirror_register_file[R14_UNDEF] = state->RegBank[UNDEFBANK][14]; +    mirror_register_file[R13_IRQ] = state->RegBank[IRQBANK][13]; +    mirror_register_file[R14_IRQ] = state->RegBank[IRQBANK][14]; +    mirror_register_file[R8_FIRQ] = state->RegBank[FIQBANK][8]; +    mirror_register_file[R9_FIRQ] = state->RegBank[FIQBANK][9]; +    mirror_register_file[R10_FIRQ] = state->RegBank[FIQBANK][10]; +    mirror_register_file[R11_FIRQ] = state->RegBank[FIQBANK][11]; +    mirror_register_file[R12_FIRQ] = state->RegBank[FIQBANK][12]; +    mirror_register_file[R13_FIRQ] = state->RegBank[FIQBANK][13]; +    mirror_register_file[R14_FIRQ] = state->RegBank[FIQBANK][14]; +    mirror_register_file[SPSR_SVC] = state->Spsr[SVCBANK]; +    mirror_register_file[SPSR_ABORT] = state->Spsr[ABORTBANK]; +    mirror_register_file[SPSR_UNDEF] = state->Spsr[UNDEFBANK]; +    mirror_register_file[SPSR_IRQ] = state->Spsr[IRQBANK]; +    mirror_register_file[SPSR_FIRQ] = state->Spsr[FIQBANK]; +#endif +	/* Execute the next instruction.  */ +	if (state->NextInstr < PRIMEPIPE) { +		decoded = state->decoded; +		loaded = state->loaded; +		pc = state->pc; +		//chy 2006-04-12, for ICE debug +		decoded_addr=state->decoded_addr; +		loaded_addr=state->loaded_addr; +	} + +	do { +            //print_func_name(state->pc); +		/* Just keep going.  */ +		isize = INSN_SIZE; +		 +		switch (state->NextInstr) { +		case SEQ: +			/* Advance the pipeline, and an S cycle.  */ +			state->Reg[15] += isize; +			pc += isize; +			instr = decoded; +			//chy 2006-04-12, for ICE debug +			have_bp = ARMul_ICE_debug(state,instr,decoded_addr); +			decoded = loaded; +			decoded_addr=loaded_addr; +			//loaded = ARMul_LoadInstrS (state, pc + (isize * 2), +			//			   isize); +			loaded_addr=pc + (isize * 2); +			if (have_bp) goto  TEST_EMULATE; +			break; + +		case NONSEQ: +			/* Advance the pipeline, and an N cycle.  */ +			state->Reg[15] += isize; +			pc += isize; +			instr = decoded; +			//chy 2006-04-12, for ICE debug +			have_bp=ARMul_ICE_debug(state,instr,decoded_addr); +			decoded = loaded; +			decoded_addr=loaded_addr; +			//loaded = ARMul_LoadInstrN (state, pc + (isize * 2), +			//			   isize); +			loaded_addr=pc + (isize * 2); +			NORMALCYCLE; +			if (have_bp) goto  TEST_EMULATE; +			break; + +		case PCINCEDSEQ: +			/* Program counter advanced, and an S cycle.  */ +			pc += isize; +			instr = decoded; +			//chy 2006-04-12, for ICE debug +			have_bp=ARMul_ICE_debug(state,instr,decoded_addr); +			decoded = loaded; +			decoded_addr=loaded_addr; +			//loaded = ARMul_LoadInstrS (state, pc + (isize * 2), +			//			   isize); +			loaded_addr=pc + (isize * 2); +			NORMALCYCLE; +			if (have_bp) goto  TEST_EMULATE; +			break; + +		case PCINCEDNONSEQ: +			/* Program counter advanced, and an N cycle.  */ +			pc += isize; +			instr = decoded; +			//chy 2006-04-12, for ICE debug +			have_bp=ARMul_ICE_debug(state,instr,decoded_addr); +			decoded = loaded; +			decoded_addr=loaded_addr; +			//loaded = ARMul_LoadInstrN (state, pc + (isize * 2), +			//			   isize); +			loaded_addr=pc + (isize * 2); +			NORMALCYCLE; +			if (have_bp) goto  TEST_EMULATE; +			break; + +		case RESUME: +			/* The program counter has been changed.  */ +			pc = state->Reg[15]; +#ifndef MODE32 +			pc = pc & R15PCBITS; +#endif +			state->Reg[15] = pc + (isize * 2); +			state->Aborted = 0; +			//chy 2004-05-25, fix bug provided by Carl van Schaik<cvansch@cse.unsw.EDU.AU> +			state->AbortAddr = 1; + +			instr = ARMul_LoadInstrN (state, pc, isize); +			//instr = ARMul_ReLoadInstr (state, pc, isize); +			//chy 2006-04-12, for ICE debug +			have_bp=ARMul_ICE_debug(state,instr,pc); +			//decoded = +			//	ARMul_ReLoadInstr (state, pc + isize, isize); +			decoded_addr=pc+isize; +			//loaded = ARMul_ReLoadInstr (state, pc + isize * 2, +			//			    isize); +			loaded_addr=pc + isize * 2; +			NORMALCYCLE; +			if (have_bp) goto  TEST_EMULATE; +			break; + +		default: +			/* The program counter has been changed.  */ +			pc = state->Reg[15]; +#ifndef MODE32 +			pc = pc & R15PCBITS; +#endif +			state->Reg[15] = pc + (isize * 2); +			state->Aborted = 0; +			//chy 2004-05-25, fix bug provided by Carl van Schaik<cvansch@cse.unsw.EDU.AU> +			state->AbortAddr = 1; + +			instr = ARMul_LoadInstrN (state, pc, isize); +			//chy 2006-04-12, for ICE debug +			have_bp=ARMul_ICE_debug(state,instr,pc); +			#if 0 +			decoded = +				ARMul_LoadInstrS (state, pc + (isize), isize); +			#endif +			decoded_addr=pc+isize; +			#if 0 +			loaded = ARMul_LoadInstrS (state, pc + (isize * 2), +						   isize); +			#endif +			loaded_addr=pc + isize * 2; +			NORMALCYCLE; +			if (have_bp) goto  TEST_EMULATE; +			break; +		} +#if 0 +        int idx = 0; +        printf("pc:%x\n", pc); +        for (;idx < 17; idx ++) { +                printf("R%d:%x\t", idx, state->Reg[idx]); +        } +        printf("\n"); +#endif +	instr = ARMul_LoadInstrN (state, pc, isize); +	state->last_instr = state->CurrInstr; +	state->CurrInstr = instr; +#if 0 +	if((state->NumInstrs % 10000000) == 0) +		printf("---|%p|---  %lld\n", pc, state->NumInstrs); +	if(state->NumInstrs > (3000000000)){ +		static int flag = 0; +		if(pc == 0x8032ccc4){ +			flag = 300; +		} +		if(flag){ +			int idx = 0; +			printf("------------------------------------\n"); +		        printf("pc:%x\n", pc); +		        for (;idx < 17; idx ++) { +                		printf("R%d:%x\t", idx, state->Reg[idx]); +		        } +			printf("\nN:%d\t Z:%d\t C:%d\t V:%d\n", state->NFlag,  state->ZFlag, state->CFlag, state->VFlag); +		        printf("\n"); +			printf("------------------------------------\n"); +			flag--; +		} +	} +#endif	 +#if DIFF_STATE +      fprintf(state->state_log, "PC:0x%x\n", pc); +      if (pc && (pc + 8) != state->Reg[15]) { +              printf("lucky dog\n"); +              printf("pc is %x, R15 is %x\n", pc, state->Reg[15]); +              //exit(-1); +      } +      for (reg_index = 0; reg_index < 16; reg_index ++) { +              if (state->Reg[reg_index] != mirror_register_file[reg_index]) { +                      fprintf(state->state_log, "R%d:0x%x\n", reg_index, state->Reg[reg_index]); +                      mirror_register_file[reg_index] = state->Reg[reg_index]; +              } +      } +      if (state->Cpsr != mirror_register_file[CPSR_REG]) { +              fprintf(state->state_log, "Cpsr:0x%x\n", state->Cpsr); +              mirror_register_file[CPSR_REG] = state->Cpsr; +      } +      if (state->RegBank[SVCBANK][13] != mirror_register_file[R13_SVC]) { +              fprintf(state->state_log, "R13_SVC:0x%x\n", state->RegBank[SVCBANK][13]); +              mirror_register_file[R13_SVC] = state->RegBank[SVCBANK][13]; +      } +      if (state->RegBank[SVCBANK][14] != mirror_register_file[R14_SVC]) { +              fprintf(state->state_log, "R14_SVC:0x%x\n", state->RegBank[SVCBANK][14]); +              mirror_register_file[R14_SVC] = state->RegBank[SVCBANK][14]; +      } +      if (state->RegBank[ABORTBANK][13] != mirror_register_file[R13_ABORT]) { +              fprintf(state->state_log, "R13_ABORT:0x%x\n", state->RegBank[ABORTBANK][13]); +              mirror_register_file[R13_ABORT] = state->RegBank[ABORTBANK][13]; +      } +      if (state->RegBank[ABORTBANK][14] != mirror_register_file[R14_ABORT]) { +              fprintf(state->state_log, "R14_ABORT:0x%x\n", state->RegBank[ABORTBANK][14]); +              mirror_register_file[R14_ABORT] = state->RegBank[ABORTBANK][14]; +      } +      if (state->RegBank[UNDEFBANK][13] != mirror_register_file[R13_UNDEF]) { +              fprintf(state->state_log, "R13_UNDEF:0x%x\n", state->RegBank[UNDEFBANK][13]); +              mirror_register_file[R13_UNDEF] = state->RegBank[UNDEFBANK][13]; +      } +      if (state->RegBank[UNDEFBANK][14] != mirror_register_file[R14_UNDEF]) { +              fprintf(state->state_log, "R14_UNDEF:0x%x\n", state->RegBank[UNDEFBANK][14]); +              mirror_register_file[R14_UNDEF] = state->RegBank[UNDEFBANK][14]; +      } +      if (state->RegBank[IRQBANK][13] != mirror_register_file[R13_IRQ]) { +              fprintf(state->state_log, "R13_IRQ:0x%x\n", state->RegBank[IRQBANK][13]); +              mirror_register_file[R13_IRQ] = state->RegBank[IRQBANK][13]; +      } +      if (state->RegBank[IRQBANK][14] != mirror_register_file[R14_IRQ]) { +              fprintf(state->state_log, "R14_IRQ:0x%x\n", state->RegBank[IRQBANK][14]); +              mirror_register_file[R14_IRQ] = state->RegBank[IRQBANK][14]; +      } +      if (state->RegBank[FIQBANK][8] != mirror_register_file[R8_FIRQ]) { +              fprintf(state->state_log, "R8_FIRQ:0x%x\n", state->RegBank[FIQBANK][8]); +              mirror_register_file[R8_FIRQ] = state->RegBank[FIQBANK][8]; +      } +      if (state->RegBank[FIQBANK][9] != mirror_register_file[R9_FIRQ]) { +              fprintf(state->state_log, "R9_FIRQ:0x%x\n", state->RegBank[FIQBANK][9]); +              mirror_register_file[R9_FIRQ] = state->RegBank[FIQBANK][9]; +      } +      if (state->RegBank[FIQBANK][10] != mirror_register_file[R10_FIRQ]) { +              fprintf(state->state_log, "R10_FIRQ:0x%x\n", state->RegBank[FIQBANK][10]); +              mirror_register_file[R10_FIRQ] = state->RegBank[FIQBANK][10]; +      } +      if (state->RegBank[FIQBANK][11] != mirror_register_file[R11_FIRQ]) { +              fprintf(state->state_log, "R11_FIRQ:0x%x\n", state->RegBank[FIQBANK][11]); +              mirror_register_file[R11_FIRQ] = state->RegBank[FIQBANK][11]; +      } +      if (state->RegBank[FIQBANK][12] != mirror_register_file[R12_FIRQ]) { +              fprintf(state->state_log, "R12_FIRQ:0x%x\n", state->RegBank[FIQBANK][12]); +              mirror_register_file[R12_FIRQ] = state->RegBank[FIQBANK][12]; +      } +      if (state->RegBank[FIQBANK][13] != mirror_register_file[R13_FIRQ]) { +              fprintf(state->state_log, "R13_FIRQ:0x%x\n", state->RegBank[FIQBANK][13]); +              mirror_register_file[R13_FIRQ] = state->RegBank[FIQBANK][13]; +      } +      if (state->RegBank[FIQBANK][14] != mirror_register_file[R14_FIRQ]) { +              fprintf(state->state_log, "R14_FIRQ:0x%x\n", state->RegBank[FIQBANK][14]); +              mirror_register_file[R14_FIRQ] = state->RegBank[FIQBANK][14]; +      } +      if (state->Spsr[SVCBANK] != mirror_register_file[SPSR_SVC]) { +              fprintf(state->state_log, "SPSR_SVC:0x%x\n", state->Spsr[SVCBANK]); +              mirror_register_file[SPSR_SVC] = state->RegBank[SVCBANK]; +      } +      if (state->Spsr[ABORTBANK] != mirror_register_file[SPSR_ABORT]) { +              fprintf(state->state_log, "SPSR_ABORT:0x%x\n", state->Spsr[ABORTBANK]); +              mirror_register_file[SPSR_ABORT] = state->RegBank[ABORTBANK]; +      } +      if (state->Spsr[UNDEFBANK] != mirror_register_file[SPSR_UNDEF]) { +              fprintf(state->state_log, "SPSR_UNDEF:0x%x\n", state->Spsr[UNDEFBANK]); +              mirror_register_file[SPSR_UNDEF] = state->RegBank[UNDEFBANK]; +      } +      if (state->Spsr[IRQBANK] != mirror_register_file[SPSR_IRQ]) { +              fprintf(state->state_log, "SPSR_IRQ:0x%x\n", state->Spsr[IRQBANK]); +              mirror_register_file[SPSR_IRQ] = state->RegBank[IRQBANK]; +      } +      if (state->Spsr[FIQBANK] != mirror_register_file[SPSR_FIRQ]) { +              fprintf(state->state_log, "SPSR_FIRQ:0x%x\n", state->Spsr[FIQBANK]); +              mirror_register_file[SPSR_FIRQ] = state->RegBank[FIQBANK]; +      } +#endif + +#if 0 +		uint32_t alex = 0; +		static int flagged = 0; +		if ((flagged == 0) && (pc == 0xb224)) +		{ +			flagged++; +		} +		if ((flagged == 1) && (pc == 0x1a800)) +		{ +			flagged++; +		} +		if (flagged == 3) { +			printf("---|%p|---  %x\n", pc, state->NumInstrs); +			for (alex = 0; alex < 15; alex++) +			{ +				printf("R%02d % 8x\n", alex, state->Reg[alex]); +			} +			printf("R%02d % 8x\n", alex, state->Reg[alex] - 8); +			printf("CPS %x%07x\n", (state->NFlag<<3 | state->ZFlag<<2 | state->CFlag<<1 | state->VFlag), state->Cpsr & 0xfffffff); +		} else { +			if (state->NumInstrs < 0x400000) +			{ +				//exit(-1); +			} +		} +#endif + +		if (state->EventSet) +			ARMul_EnvokeEvent (state); + +#if 0 +		/* do profiling for code coverage */ +		if (skyeye_config.code_cov.prof_on) +			cov_prof(EXEC_FLAG, pc); +#endif +//2003-07-11 chy: for test +#if 0 +		if (skyeye_config.log.logon >= 1) { +			if (state->NumInstrs >= skyeye_config.log.start && +			    state->NumInstrs <= skyeye_config.log.end) { +				static int mybegin = 0; +				static int myinstrnum = 0; +				if (mybegin == 0) +					mybegin = 1; +#if 0 +				if (state->NumInstrs == 3695) { +					printf ("***********SKYEYE: numinstr = 3695\n"); +				} +				static int mybeg2 = 0; +				static int mybeg3 = 0; +				static int mybeg4 = 0; +				static int mybeg5 = 0; + +				if (pc == 0xa0008000) { +					//mybegin=1; +					printf ("************SKYEYE: real vmlinux begin now  numinstr is %llu  ****************\n", state->NumInstrs); +				} + +				//chy 2003-09-02 test fiq +				if (state->NumInstrs == 67347000) { +					printf ("***********SKYEYE: numinstr = 67347000, begin log\n"); +					mybegin = 1; +				} +				if (pc == 0xc00087b4) {	//numinstr=67348714 +					mybegin = 1; +					printf ("************SKYEYE: test irq now  numinstr is %llu  ****************\n", state->NumInstrs); +				} +				if (pc == 0xc00087b8) {	//in start_kernel::sti() +					mybeg4 = 1; +					printf ("************SKYEYE: startkerenl: sti now  numinstr is %llu  ********\n", state->NumInstrs); +				} +				/*if (pc==0xc001e4f4||pc==0xc001e4f8||pc==0xc001e4fc||pc==0xc001e500||pc==0xffff0004) { //MRA instr */ +				if (pc == 0xc001e500) {	//MRA instr +					mybeg5 = 1; +					printf ("************SKYEYE: MRA instr now  numinstr is %llu  ********\n", state->NumInstrs); +				} +				if (pc >= 0xc0000000 && mybeg2 == 0) { +					mybeg2 = 1; +					printf ("************SKYEYE: enable mmu&cache, now numinstr is %llu **************\n", state->NumInstrs); +					SKYEYE_OUTREGS (stderr); +					printf ("************************************************************************\n"); +				} +				//chy 2003-09-01 test after tlb-flush  +				if (pc == 0xc00261ac) { +					//sleep(2); +					mybeg3 = 1; +					printf ("************SKYEYE: after tlb-flush  numinstr is %llu  ****************\n", state->NumInstrs); +				} +				if (mybeg3 == 1) { +					SKYEYE_OUTREGS (skyeye_logfd); +					SKYEYE_OUTMOREREGS (skyeye_logfd); +					fprintf (skyeye_logfd, "\n"); +				} +#endif +				if (mybegin == 1) { +					//fprintf(skyeye_logfd,"p %x,i %x,d %x,l %x,",pc,instr,decoded,loaded); +					//chy for test 20050729 +					/*if (state->NumInstrs>=3302294) { +					   if (pc==0x100c9d4 && instr==0xe1b0f00e){ +					   chy_debug(); +					   printf("*********************************************\n"); +					   printf("******SKYEYE N %llx :p %x,i %x\n  SKYEYE******\n",state->NumInstrs,pc,instr); +					   printf("*********************************************\n"); +					   } +					 */ +					if (skyeye_config.log.logon >= 1) +					/* +						fprintf (skyeye_logfd, +							 "N %llx :p %x,i %x,", +							 state->NumInstrs, pc, +#ifdef MODET +							 TFLAG ? instr & 0xffff : instr +#else +							 instr +#endif +							); +					*/ +						fprintf(skyeye_logfd, "pc=0x%x,r3=0x%x\n", pc, state->Reg[3]); +					if (skyeye_config.log.logon >= 2) +						SKYEYE_OUTREGS (skyeye_logfd); +					if (skyeye_config.log.logon >= 3) +						SKYEYE_OUTMOREREGS +							(skyeye_logfd); +					//fprintf (skyeye_logfd, "\n"); +					if (skyeye_config.log.length > 0) { +						myinstrnum++; +						if (myinstrnum >= +						    skyeye_config.log. +						    length) { +							myinstrnum = 0; +							fflush (skyeye_logfd); +							fseek (skyeye_logfd, +							       0L, SEEK_SET); +						} +					} +				} +				//SKYEYE_OUTREGS(skyeye_logfd); +				//SKYEYE_OUTMOREREGS(skyeye_logfd); +			} +		} +#endif +#if 0				/* Enable this for a helpful bit of debugging when tracing is needed.  */ +		fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr); +		if (instr == 0) +			abort (); +#endif +#if 0				/* Enable this code to help track down stack alignment bugs.  */ +		{ +			static ARMword old_sp = -1; + +			if (old_sp != state->Reg[13]) { +				old_sp = state->Reg[13]; +				fprintf (stderr, +					 "pc: %08x: SP set to %08x%s\n", +					 pc & ~1, old_sp, +					 (old_sp % 8) ? " [UNALIGNED!]" : ""); +			} +		} +#endif +		/* Any exceptions ?  */ +		if (state->NresetSig == LOW) { +			ARMul_Abort (state, ARMul_ResetV); + +			/*added energy_prof statement by ksh in 2004-11-26 */ +			//chy 2005-07-28 for standalone +			//ARMul_do_energy(state,instr,pc); +			break; +		} +		else if (!state->NfiqSig && !FFLAG) { +			ARMul_Abort (state, ARMul_FIQV); +			/*added energy_prof statement by ksh in 2004-11-26 */ +			//chy 2005-07-28 for standalone +			//ARMul_do_energy(state,instr,pc); +			break; +		} +		else if (!state->NirqSig && !IFLAG) { +			ARMul_Abort (state, ARMul_IRQV); +			/*added energy_prof statement by ksh in 2004-11-26 */ +			//chy 2005-07-28 for standalone +			//ARMul_do_energy(state,instr,pc); +			break; +		} + +//teawater add for arm2x86 2005.04.26------------------------------------------- +#if 0 +//        if (state->pc == 0xc011a868 || state->pc == 0xc011a86c) { +        if (state->NumInstrs == 1671574 || state->NumInstrs == 1671573 || state->NumInstrs == 1671572 +            || state->NumInstrs == 1671575) { +                for (reg_index = 0; reg_index < 16; reg_index ++) { +                    printf("R%d:%x\t", reg_index, state->Reg[reg_index]); +                } +                printf("\n"); +        } +#endif +		if (state->tea_pc) { +			int i; + +			if (state->tea_reg_fd) { +				fprintf (state->tea_reg_fd, "\n"); +				for (i = 0; i < 15; i++) { +					fprintf (state->tea_reg_fd, "%x,", +						 state->Reg[i]); +				} +				fprintf (state->tea_reg_fd, "%x,", pc); +				state->Cpsr = ARMul_GetCPSR (state); +				fprintf (state->tea_reg_fd, "%x\n", +					 state->Cpsr); +			} +			else { +				printf ("\n"); +				for (i = 0; i < 15; i++) { +					printf ("%x,", state->Reg[i]); +				} +				printf ("%x,", pc); +				state->Cpsr = ARMul_GetCPSR (state); +				printf ("%x\n", state->Cpsr); +			} +		} +//AJ2D-------------------------------------------------------------------------- + +		if (state->CallDebug > 0) { +			instr = ARMul_Debug (state, pc, instr); +			if (state->Emulate < ONCE) { +				state->NextInstr = RESUME; +				break; +			} +			if (state->Debug) { +				fprintf (stderr, +					 "sim: At %08lx Instr %08lx Mode %02lx\n", +					 pc, instr, state->Mode); +				(void) fgetc (stdin); +			} +		} +		else if (state->Emulate < ONCE) { +			state->NextInstr = RESUME; +			break; +		} +		//io_do_cycle (state); +		state->NumInstrs++; +		#if 0 +		if (state->NumInstrs % 10000000 == 0) { +				printf("10 MIPS instr have been executed\n"); +		} +		#endif + +#ifdef MODET +		/* Provide Thumb instruction decoding. If the processor is in Thumb +		   mode, then we can simply decode the Thumb instruction, and map it +		   to the corresponding ARM instruction (by directly loading the +		   instr variable, and letting the normal ARM simulator +		   execute). There are some caveats to ensure that the correct +		   pipelined PC value is used when executing Thumb code, and also for +		   dealing with the BL instruction.  */ +		if (TFLAG) { +			ARMword new; + +			/* Check if in Thumb mode.  */ +			switch (ARMul_ThumbDecode (state, pc, instr, &new)) { +			case t_undefined: +				/* This is a Thumb instruction.  */ +				ARMul_UndefInstr (state, instr); +				_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; + +			case t_branch: +				/* Already processed.  */ +				_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; + +			case t_decoded: +				/* ARM instruction available.  */ +				//printf("t decode %04lx -> %08lx\n", instr & 0xffff, new); +				instr = new; +				/* So continue instruction decoding.  */ +				break; +			default: +				break; +			} +		} +#endif + +		/* Check the condition codes.  */ +		if ((temp = TOPBITS (28)) == AL) { +			/* Vile deed in the need for speed. */ +			goto mainswitch; +		} + +		/* Check the condition code. */ +		switch ((int) TOPBITS (28)) { +		case AL: +			temp = TRUE; +			break; +		case NV: + +			/* shenoubang add for armv7 instr dmb 2012-3-11 */ +			if (state->is_v7) { +				if ((instr & 0x0fffff00) == 0x057ff000) { +					switch((instr >> 4) & 0xf) { +						case 4: /* dsb */ +						case 5: /* dmb */ +						case 6: /* isb */ +							// TODO: do no implemented thes instr +							_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +					} +				} +			} +			/* dyf add for armv6 instruct CPS 2010.9.17 */ +			if (state->is_v6) { +				/* clrex do nothing here temporary */ +				if (instr == 0xf57ff01f) { +					//printf("clrex \n"); +					ERROR_LOG(ARM11, "Instr = 0x%x, pc = 0x%x, clrex instr!!\n", instr, pc); +#if 0 +					int i; +					for(i = 0; i < 128; i++){ +						state->exclusive_tag_array[i] = 0xffffffff; +					} +#endif +					/* shenoubang 2012-3-14 refer the dyncom_interpreter */ +					state->exclusive_tag_array[0] = 0xFFFFFFFF; +					state->exclusive_access_state = 0; +					_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +				} + +				if (BITS(20, 27) == 0x10) { +					if (BIT(19)) { +						if (BIT(8)) { +							if (BIT(18)) +								state->Cpsr |= 1<<8; +							else +								state->Cpsr &= ~(1<<8); +						} +						if (BIT(7)) { +							if (BIT(18)) +								state->Cpsr |= 1<<7; +							else +								state->Cpsr &= ~(1<<7); +							ASSIGNINT (state->Cpsr & INTBITS); +						} +						if (BIT(6)) { +							if (BIT(18)) +								state->Cpsr |= 1<<6; +							else +								state->Cpsr &= ~(1<<6); +							ASSIGNINT (state->Cpsr & INTBITS); +						} +					} +					if (BIT(17)) { +						state->Cpsr |= BITS(0, 4); +						printf("skyeye test state->Mode\n"); +						if (state->Mode != (state->Cpsr & MODEBITS)) { +							state->Mode = +								ARMul_SwitchMode (state, state->Mode, +										  state->Cpsr & MODEBITS); + +							state->NtransSig = (state->Mode & 3) ? HIGH : LOW; +						} +					} +					_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +				} +			} +			if (state->is_v5) { +				if (BITS (25, 27) == 5) {	/* BLX(1) */ +					ARMword dest; + +					state->Reg[14] = pc + 4; + +					/* Force entry into Thumb mode.  */ +					dest = pc + 8 + 1; +					if (BIT (23)) +						dest += (NEGBRANCH + +							 (BIT (24) << 1)); +					else +						dest += POSBRANCH + +							(BIT (24) << 1); + +					WriteR15Branch (state, dest); +					_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +				} +				else if ((instr & 0xFC70F000) == 0xF450F000) { +					/* The PLD instruction.  Ignored.  */ +					_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +				} +				else if (((instr & 0xfe500f00) == 0xfc100100) +					 || ((instr & 0xfe500f00) == +					     0xfc000100)) { +					/* wldrw and wstrw are unconditional.  */ +					goto mainswitch; +				} +				else { +					/* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2.  */ +					ARMul_UndefInstr (state, instr); +				} +			} +			temp = FALSE; +			break; +		case EQ: +			temp = ZFLAG; +			break; +		case NE: +			temp = !ZFLAG; +			break; +		case VS: +			temp = VFLAG; +			break; +		case VC: +			temp = !VFLAG; +			break; +		case MI: +			temp = NFLAG; +			break; +		case PL: +			temp = !NFLAG; +			break; +		case CS: +			temp = CFLAG; +			break; +		case CC: +			temp = !CFLAG; +			break; +		case HI: +			temp = (CFLAG && !ZFLAG); +			break; +		case LS: +			temp = (!CFLAG || ZFLAG); +			break; +		case GE: +			temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG)); +			break; +		case LT: +			temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)); +			break; +		case GT: +			temp = ((!NFLAG && !VFLAG && !ZFLAG) +				|| (NFLAG && VFLAG && !ZFLAG)); +			break; +		case LE: +			temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) +				|| ZFLAG; +			break; +		}		/* cc check */ + +//chy 2003-08-24 now #if 0 .... #endif  process cp14, cp15.reg14, I disable it... +#if 0 +		/* Handle the Clock counter here.  */ +		if (state->is_XScale) { +			ARMword cp14r0; +			int ok; + +			ok = state->CPRead[14] (state, 0, &cp14r0); + +			if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE)) { +				unsigned int newcycles, nowtime = +					ARMul_Time (state); + +				newcycles = nowtime - state->LastTime; +				state->LastTime = nowtime; + +				if (cp14r0 & ARMul_CP14_R0_CCD) { +					if (state->CP14R0_CCD == -1) +						state->CP14R0_CCD = newcycles; +					else +						state->CP14R0_CCD += +							newcycles; + +					if (state->CP14R0_CCD >= 64) { +						newcycles = 0; + +						while (state->CP14R0_CCD >= +						       64) +							state->CP14R0_CCD -= +								64, +								newcycles++; + +						goto check_PMUintr; +					} +				} +				else { +					ARMword cp14r1; +					int do_int = 0; + +					state->CP14R0_CCD = -1; +				      check_PMUintr: +					cp14r0 |= ARMul_CP14_R0_FLAG2; +					(void) state->CPWrite[14] (state, 0, +								   cp14r0); + +					ok = state->CPRead[14] (state, 1, +								&cp14r1); + +					/* Coded like this for portability.  */ +					while (ok && newcycles) { +						if (cp14r1 == 0xffffffff) { +							cp14r1 = 0; +							do_int = 1; +						} +						else +							cp14r1++; + +						newcycles--; +					} + +					(void) state->CPWrite[14] (state, 1, +								   cp14r1); + +					if (do_int +					    && (cp14r0 & +						ARMul_CP14_R0_INTEN2)) { +						ARMword temp; + +						if (state-> +						    CPRead[13] (state, 8, +								&temp) +						    && (temp & +							ARMul_CP13_R8_PMUS)) +							ARMul_Abort (state, +								     ARMul_FIQV); +						else +							ARMul_Abort (state, +								     ARMul_IRQV); +					} +				} +			} +		} + +		/* Handle hardware instructions breakpoints here.  */ +		if (state->is_XScale) { +			if ((pc | 3) == (read_cp15_reg (14, 0, 8) | 2) +			    || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2)) { +				if (XScale_debug_moe +				    (state, ARMul_CP14_R10_MOE_IB)) +					ARMul_OSHandleSWI (state, +							   SWI_Breakpoint); +			} +		} +#endif + +		/* Actual execution of instructions begins here.  */ +		/* If the condition codes don't match, stop here.  */ +		if (temp) { +		      mainswitch: + +			if (state->is_XScale) { +				if (BIT (20) == 0 && BITS (25, 27) == 0) { +					if (BITS (4, 7) == 0xD) { +						/* XScale Load Consecutive insn.  */ +						ARMword temp = +							GetLS7RHS (state, +								   instr); +						ARMword temp2 = +							BIT (23) ? LHS + +							temp : LHS - temp; +						ARMword addr = +							BIT (24) ? temp2 : +							LHS; + +						if (BIT (12)) +							ARMul_UndefInstr +								(state, +								 instr); +						else if (addr & 7) +							/* Alignment violation.  */ +							ARMul_Abort (state, +								     ARMul_DataAbortV); +						else { +							int wb = BIT (21) +								|| +								(!BIT (24)); + +							state->Reg[BITS +								   (12, 15)] = +								ARMul_LoadWordN +								(state, addr); +							state->Reg[BITS +								   (12, +								    15) + 1] = +								ARMul_LoadWordN +								(state, +								 addr + 4); +							if (wb) +								LSBase = temp2; +						} + +						_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +					} +					else if (BITS (4, 7) == 0xF) { +						/* XScale Store Consecutive insn.  */ +						ARMword temp = +							GetLS7RHS (state, +								   instr); +						ARMword temp2 = +							BIT (23) ? LHS + +							temp : LHS - temp; +						ARMword addr = +							BIT (24) ? temp2 : +							LHS; + +						if (BIT (12)) +							ARMul_UndefInstr +								(state, +								 instr); +						else if (addr & 7) +							/* Alignment violation.  */ +							ARMul_Abort (state, +								     ARMul_DataAbortV); +						else { +							ARMul_StoreWordN +								(state, addr, +								 state-> +								 Reg[BITS +								     (12, +								      15)]); +							ARMul_StoreWordN +								(state, +								 addr + 4, +								 state-> +								 Reg[BITS +								     (12, +								      15) + +								     1]); + +							if (BIT (21) +							    || !BIT (24)) +								LSBase = temp2; +						} + +						_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +					} +				} +				//chy 2003-09-03 TMRRC(iwmmxt.c) and MRA has the same decoded instr???? +				//Now, I commit iwmmxt process, may be future, I will change it!!!!  +				//if (ARMul_HandleIwmmxt (state, instr)) +				//        _assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +			} + +			/* shenoubang sbfx and ubfx instr 2012-3-16 */ +			if (state->is_v6) { +				unsigned int m, lsb, width, Rd, Rn, data; +				Rd = Rn = lsb = width = data = m = 0; + +				//printf("helloworld\n"); +				if ((((int) BITS (21, 27)) == 0x3f) && (((int) BITS (4, 6)) == 0x5)) { +					m = (unsigned)BITS(7, 11); +					width = (unsigned)BITS(16, 20); +					Rd = (unsigned)BITS(12, 15); +					Rn = (unsigned)BITS(0, 3); +					if ((Rd == 15) || (Rn == 15)) { +						ARMul_UndefInstr (state, instr); +					} +					else if ((m + width) < 32) { +						data = state->Reg[Rn]; +						state->Reg[Rd] ^= state->Reg[Rd]; +						state->Reg[Rd] = +							((ARMword)(data << (31 -(m + width))) >> ((31 - (m + width)) + (m))); +						//SKYEYE_LOG_IN_CLR(RED, "UBFX: In %s, line = %d, Reg_src[%d] = 0x%x, Reg_d[%d] = 0x%x, m = %d, width = %d, Rd = %d, Rn = %d\n", +						//		__FUNCTION__, __LINE__, Rn, data, Rd, state->Reg[Rd], m, width + 1, Rd, Rn); +						_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +					} +				} // ubfx instr +				else if ((((int) BITS (21, 27)) == 0x3d) && (((int) BITS (4, 6)) == 0x5)) { +					int tmp = 0; +					Rd = BITS(12, 15); Rn = BITS(0, 3); +					lsb = BITS(7, 11); width = BITS(16, 20); +					if ((Rd == 15) || (Rn == 15)) { +						ARMul_UndefInstr (state, instr); +					} +					else if ((lsb + width) < 32) { +						state->Reg[Rd] ^= state->Reg[Rd]; +						data = state->Reg[Rn]; +						tmp = (data << (32 - (lsb + width + 1))); +						state->Reg[Rd] = (tmp >> (32 - (lsb + width + 1))); +						//SKYEYE_LOG_IN_CLR(RED, "sbfx: In %s, line = %d, pc = 0x%x, instr = 0x%x,Rd = 0x%x, \ +								Rn = 0x%x, lsb = %d, width = %d, Rs[%d] = 0x%x, Rd[%d] = 0x%x\n", +						//		__func__, __LINE__, pc, instr, Rd, Rn, lsb, width + 1, Rn, state->Reg[Rn], Rd, state->Reg[Rd]); +						_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +					} +				} // sbfx instr +				else if ((((int)BITS(21, 27)) == 0x3e) && ((int)BITS(4, 6) == 0x1)) { +					//(ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) +					unsigned msb ,tmp_rn, tmp_rd, dst; +					msb = tmp_rd = tmp_rn = dst = 0; +					Rd = BITS(12, 15); Rn = BITS(0, 3); +					lsb = BITS(7, 11); msb = BITS(16, 20); +					if ((Rd == 15)) { +						ARMul_UndefInstr (state, instr); +					} +					else if ((Rn == 15)) { +						data = state->Reg[Rd]; +						tmp_rd = ((ARMword)(data << (31 - lsb)) >> (31 - lsb)); +						dst = ((data >> msb) << (msb - lsb)); +						dst = (dst << lsb) | tmp_rd; +						DEBUG_LOG(ARM11, "BFC instr: msb = %d, lsb = %d, Rd[%d] : 0x%x, dst = 0x%x\n", +							msb, lsb, Rd, state->Reg[Rd], dst); +						_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +					} // bfc instr +					else if (((msb >= lsb) && (msb < 32))) { +						data = state->Reg[Rn]; +						tmp_rn = ((ARMword)(data << (31 - (msb - lsb))) >> (31 - (msb - lsb))); +						data = state->Reg[Rd]; +						tmp_rd = ((ARMword)(data << (31 - lsb)) >> (31 - lsb)); +						dst = ((data >> msb) << (msb - lsb)) | tmp_rn; +						dst = (dst << lsb) | tmp_rd; +						DEBUG_LOG(ARM11, "BFI instr:msb = %d, lsb = %d, Rd[%d] : 0x%x, Rn[%d]: 0x%x, dst = 0x%x\n", +							msb, lsb, Rd, state->Reg[Rd], Rn, state->Reg[Rn], dst); +						_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +					} // bfi instr +				} +			} +			 +			switch ((int) BITS (20, 27)) { +				/* Data Processing Register RHS Instructions.  */ + +			case 0x00:	/* AND reg and MUL */ +#ifdef MODET +				if (BITS (4, 11) == 0xB) { +					/* STRH register offset, no write-back, down, post indexed.  */ +					SHDOWNWB (); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +#endif +				if (BITS (4, 7) == 9) { +					/* MUL */ +					rhs = state->Reg[MULRHSReg]; +					//if (MULLHSReg == MULDESTReg) { +					if(0){ /* For armv6, the restriction is removed */ +						UNDEF_MULDestEQOp1; +						state->Reg[MULDESTReg] = 0; +					} +					else if (MULDESTReg != 15) +						state->Reg[MULDESTReg] = +							state-> +							Reg[MULLHSReg] * rhs; +					else +						UNDEF_MULPCDest; + +					for (dest = 0, temp = 0; dest < 32; +					     dest++) +						if (rhs & (1L << dest)) +							temp = dest; + +					/* Mult takes this many/2 I cycles.  */ +					ARMul_Icycles (state, +						       ARMul_MultTable[temp], +						       0L); +				} +				else { +					/* AND reg.  */ +					rhs = DPRegRHS; +					dest = LHS & rhs; +					WRITEDEST (dest); +				} +				break; + +			case 0x01:	/* ANDS reg and MULS */ +#ifdef MODET +				if ((BITS (4, 11) & 0xF9) == 0x9) +					/* LDR register offset, no write-back, down, post indexed.  */ +					LHPOSTDOWN (); +				/* Fall through to rest of decoding.  */ +#endif +				if (BITS (4, 7) == 9) { +					/* MULS */ +					rhs = state->Reg[MULRHSReg]; + +					//if (MULLHSReg == MULDESTReg) { +					if(0){ +						printf("Something in %d line\n", __LINE__); +						UNDEF_WARNING; +						UNDEF_MULDestEQOp1; +						state->Reg[MULDESTReg] = 0; +						CLEARN; +						SETZ; +					} +					else if (MULDESTReg != 15) { +						dest = state->Reg[MULLHSReg] * +							rhs; +						ARMul_NegZero (state, dest); +						state->Reg[MULDESTReg] = dest; +					} +					else +						UNDEF_MULPCDest; + +					for (dest = 0, temp = 0; dest < 32; +					     dest++) +						if (rhs & (1L << dest)) +							temp = dest; + +					/* Mult takes this many/2 I cycles.  */ +					ARMul_Icycles (state, +						       ARMul_MultTable[temp], +						       0L); +				} +				else { +					/* ANDS reg.  */ +					rhs = DPSRegRHS; +					dest = LHS & rhs; +					WRITESDEST (dest); +				} +				break; + +			case 0x02:	/* EOR reg and MLA */ +#ifdef MODET +				if (BITS (4, 11) == 0xB) { +					/* STRH register offset, write-back, down, post indexed.  */ +					SHDOWNWB (); +					break; +				} +#endif +				if (BITS (4, 7) == 9) {	/* MLA */ +					rhs = state->Reg[MULRHSReg]; +					#if 0 +					if (MULLHSReg == MULDESTReg) { +						UNDEF_MULDestEQOp1; +						state->Reg[MULDESTReg] = +							state->Reg[MULACCReg]; +					} +					else if (MULDESTReg != 15){ +					#endif +					if (MULDESTReg != 15){ +						state->Reg[MULDESTReg] = +							state-> +							Reg[MULLHSReg] * rhs + +							state->Reg[MULACCReg]; +					} +					else +						UNDEF_MULPCDest; + +					for (dest = 0, temp = 0; dest < 32; +					     dest++) +						if (rhs & (1L << dest)) +							temp = dest; + +					/* Mult takes this many/2 I cycles.  */ +					ARMul_Icycles (state, +						       ARMul_MultTable[temp], +						       0L); +				} +				else { +					rhs = DPRegRHS; +					dest = LHS ^ rhs; +					WRITEDEST (dest); +				} +				break; + +			case 0x03:	/* EORS reg and MLAS */ +#ifdef MODET +				if ((BITS (4, 11) & 0xF9) == 0x9) +					/* LDR register offset, write-back, down, post-indexed.  */ +					LHPOSTDOWN (); +				/* Fall through to rest of the decoding.  */ +#endif +				if (BITS (4, 7) == 9) { +					/* MLAS */ +					rhs = state->Reg[MULRHSReg]; +					//if (MULLHSReg == MULDESTReg) { +					if (0) { +						UNDEF_MULDestEQOp1; +						dest = state->Reg[MULACCReg]; +						ARMul_NegZero (state, dest); +						state->Reg[MULDESTReg] = dest; +					} +					else if (MULDESTReg != 15) { +						dest = state->Reg[MULLHSReg] * +							rhs + +							state->Reg[MULACCReg]; +						ARMul_NegZero (state, dest); +						state->Reg[MULDESTReg] = dest; +					} +					else +						UNDEF_MULPCDest; + +					for (dest = 0, temp = 0; dest < 32; +					     dest++) +						if (rhs & (1L << dest)) +							temp = dest; + +					/* Mult takes this many/2 I cycles.  */ +					ARMul_Icycles (state, +						       ARMul_MultTable[temp], +						       0L); +				} +				else { +					/* EORS Reg.  */ +					rhs = DPSRegRHS; +					dest = LHS ^ rhs; +					WRITESDEST (dest); +				} +				break; + +			case 0x04:	/* SUB reg */ +#ifdef MODET +				if (BITS (4, 7) == 0xB) { +					/* STRH immediate offset, no write-back, down, post indexed.  */ +					SHDOWNWB (); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +#endif +				rhs = DPRegRHS; +				dest = LHS - rhs; +				WRITEDEST (dest); +				break; + +			case 0x05:	/* SUBS reg */ +#ifdef MODET +				if ((BITS (4, 7) & 0x9) == 0x9) +					/* LDR immediate offset, no write-back, down, post indexed.  */ +					LHPOSTDOWN (); +				/* Fall through to the rest of the instruction decoding.  */ +#endif +				lhs = LHS; +				rhs = DPRegRHS; +				dest = lhs - rhs; + +				if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { +					ARMul_SubCarry (state, lhs, rhs, +							dest); +					ARMul_SubOverflow (state, lhs, rhs, +							   dest); +				} +				else { +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x06:	/* RSB reg */ +#ifdef MODET +				if (BITS (4, 7) == 0xB) { +					/* STRH immediate offset, write-back, down, post indexed.  */ +					SHDOWNWB (); +					break; +				} +#endif +				rhs = DPRegRHS; +				dest = rhs - LHS; +				WRITEDEST (dest); +				break; + +			case 0x07:	/* RSBS reg */ +#ifdef MODET +				if ((BITS (4, 7) & 0x9) == 0x9) +					/* LDR immediate offset, write-back, down, post indexed.  */ +					LHPOSTDOWN (); +				/* Fall through to remainder of instruction decoding.  */ +#endif +				lhs = LHS; +				rhs = DPRegRHS; +				dest = rhs - lhs; + +				if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { +					ARMul_SubCarry (state, rhs, lhs, +							dest); +					ARMul_SubOverflow (state, rhs, lhs, +							   dest); +				} +				else { +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x08:	/* ADD reg */ +#ifdef MODET +				if (BITS (4, 11) == 0xB) { +					/* STRH register offset, no write-back, up, post indexed.  */ +					SHUPWB (); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +#endif +#ifdef MODET +				if (BITS (4, 7) == 0x9) { +					/* MULL */ +					/* 32x32 = 64 */ +					ARMul_Icycles (state, +						       Multiply64 (state, +								   instr, +								   LUNSIGNED, +								   LDEFAULT), +						       0L); +					break; +				} +#endif +				rhs = DPRegRHS; +				dest = LHS + rhs; +				WRITEDEST (dest); +				break; + +			case 0x09:	/* ADDS reg */ +#ifdef MODET +				if ((BITS (4, 11) & 0xF9) == 0x9) +					/* LDR register offset, no write-back, up, post indexed.  */ +					LHPOSTUP (); +				/* Fall through to remaining instruction decoding.  */ +#endif +#ifdef MODET +				if (BITS (4, 7) == 0x9) { +					/* MULL */ +					/* 32x32=64 */ +					ARMul_Icycles (state, +						       Multiply64 (state, +								   instr, +								   LUNSIGNED, +								   LSCC), 0L); +					break; +				} +#endif +				lhs = LHS; +				rhs = DPRegRHS; +				dest = lhs + rhs; +				ASSIGNZ (dest == 0); +				if ((lhs | rhs) >> 30) { +					/* Possible C,V,N to set.  */ +					ASSIGNN (NEG (dest)); +					ARMul_AddCarry (state, lhs, rhs, +							dest); +					ARMul_AddOverflow (state, lhs, rhs, +							   dest); +				} +				else { +					CLEARN; +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x0a:	/* ADC reg */ +#ifdef MODET +				if (BITS (4, 11) == 0xB) { +					/* STRH register offset, write-back, up, post-indexed.  */ +					SHUPWB (); +					break; +				} +				if (BITS (4, 7) == 0x9) { +					/* MULL */ +					/* 32x32=64 */ +					ARMul_Icycles (state, +						       MultiplyAdd64 (state, +								      instr, +								      LUNSIGNED, +								      LDEFAULT), +						       0L); +					break; +				} +#endif +				rhs = DPRegRHS; +				dest = LHS + rhs + CFLAG; +				WRITEDEST (dest); +				break; + +			case 0x0b:	/* ADCS reg */ +#ifdef MODET +				if ((BITS (4, 11) & 0xF9) == 0x9) +					/* LDR register offset, write-back, up, post indexed.  */ +					LHPOSTUP (); +				/* Fall through to remaining instruction decoding.  */ +				if (BITS (4, 7) == 0x9) { +					/* MULL */ +					/* 32x32=64 */ +					ARMul_Icycles (state, +						       MultiplyAdd64 (state, +								      instr, +								      LUNSIGNED, +								      LSCC), +						       0L); +					break; +				} +#endif +				lhs = LHS; +				rhs = DPRegRHS; +				dest = lhs + rhs + CFLAG; +				ASSIGNZ (dest == 0); +				if ((lhs | rhs) >> 30) { +					/* Possible C,V,N to set.  */ +					ASSIGNN (NEG (dest)); +					ARMul_AddCarry (state, lhs, rhs, +							dest); +					ARMul_AddOverflow (state, lhs, rhs, +							   dest); +				} +				else { +					CLEARN; +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x0c:	/* SBC reg */ +#ifdef MODET +				if (BITS (4, 7) == 0xB) { +					/* STRH immediate offset, no write-back, up post indexed.  */ +					SHUPWB (); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0x9) { +					/* MULL */ +					/* 32x32=64 */ +					ARMul_Icycles (state, +						       Multiply64 (state, +								   instr, +								   LSIGNED, +								   LDEFAULT), +						       0L); +					break; +				} +#endif +				rhs = DPRegRHS; +				dest = LHS - rhs - !CFLAG; +				WRITEDEST (dest); +				break; + +			case 0x0d:	/* SBCS reg */ +#ifdef MODET +				if ((BITS (4, 7) & 0x9) == 0x9) +					/* LDR immediate offset, no write-back, up, post indexed.  */ +					LHPOSTUP (); + +				if (BITS (4, 7) == 0x9) { +					/* MULL */ +					/* 32x32=64 */ +					ARMul_Icycles (state, +						       Multiply64 (state, +								   instr, +								   LSIGNED, +								   LSCC), 0L); +					break; +				} +#endif +				lhs = LHS; +				rhs = DPRegRHS; +				dest = lhs - rhs - !CFLAG; +				if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { +					ARMul_SubCarry (state, lhs, rhs, +							dest); +					ARMul_SubOverflow (state, lhs, rhs, +							   dest); +				} +				else { +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x0e:	/* RSC reg */ +#ifdef MODET +				if (BITS (4, 7) == 0xB) { +					/* STRH immediate offset, write-back, up, post indexed.  */ +					SHUPWB (); +					break; +				} + +				if (BITS (4, 7) == 0x9) { +					/* MULL */ +					/* 32x32=64 */ +					ARMul_Icycles (state, +						       MultiplyAdd64 (state, +								      instr, +								      LSIGNED, +								      LDEFAULT), +						       0L); +					break; +				} +#endif +				rhs = DPRegRHS; +				dest = rhs - LHS - !CFLAG; +				WRITEDEST (dest); +				break; + +			case 0x0f:	/* RSCS reg */ +#ifdef MODET +				if ((BITS (4, 7) & 0x9) == 0x9) +					/* LDR immediate offset, write-back, up, post indexed.  */ +					LHPOSTUP (); +				/* Fall through to remaining instruction decoding.  */ + +				if (BITS (4, 7) == 0x9) { +					/* MULL */ +					/* 32x32=64 */ +					ARMul_Icycles (state, +						       MultiplyAdd64 (state, +								      instr, +								      LSIGNED, +								      LSCC), +						       0L); +					break; +				} +#endif +				lhs = LHS; +				rhs = DPRegRHS; +				dest = rhs - lhs - !CFLAG; + +				if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { +					ARMul_SubCarry (state, rhs, lhs, +							dest); +					ARMul_SubOverflow (state, rhs, lhs, +							   dest); +				} +				else { +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x10:	/* TST reg and MRS CPSR and SWP word.  */ +				if (state->is_v5e) { +					if (BIT (4) == 0 && BIT (7) == 1) { +						/* ElSegundo SMLAxy insn.  */ +						ARMword op1 = +							state-> +							Reg[BITS (0, 3)]; +						ARMword op2 = +							state-> +							Reg[BITS (8, 11)]; +						ARMword Rn = +							state-> +							Reg[BITS (12, 15)]; + +						if (BIT (5)) +							op1 >>= 16; +						if (BIT (6)) +							op2 >>= 16; +						op1 &= 0xFFFF; +						op2 &= 0xFFFF; +						if (op1 & 0x8000) +							op1 -= 65536; +						if (op2 & 0x8000) +							op2 -= 65536; +						op1 *= op2; +						//printf("SMLA_INST:BB,op1=0x%x, op2=0x%x. Rn=0x%x\n", op1, op2, Rn); +						if (AddOverflow +						    (op1, Rn, op1 + Rn)) +							SETS; +						state->Reg[BITS (16, 19)] = +							op1 + Rn; +						break; +					} + +					if (BITS (4, 11) == 5) { +						/* ElSegundo QADD insn.  */ +						ARMword op1 = +							state-> +							Reg[BITS (0, 3)]; +						ARMword op2 = +							state-> +							Reg[BITS (16, 19)]; +						ARMword result = op1 + op2; +						if (AddOverflow +						    (op1, op2, result)) { +							result = POS (result) +								? 0x80000000 : +								0x7fffffff; +							SETS; +						} +						state->Reg[BITS (12, 15)] = +							result; +						break; +					} +				} +#ifdef MODET +				if (BITS (4, 11) == 0xB) { +					/* STRH register offset, no write-back, down, pre indexed.  */ +					SHPREDOWN (); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +#endif +				if (BITS (4, 11) == 9) { +					/* SWP */ +					UNDEF_SWPPC; +					temp = LHS; +					BUSUSEDINCPCS; +#ifndef MODE32 +					if (VECTORACCESS (temp) +					    || ADDREXCEPT (temp)) { +						INTERNALABORT (temp); +						(void) ARMul_LoadWordN (state, +									temp); +						(void) ARMul_LoadWordN (state, +									temp); +					} +					else +#endif +						dest = ARMul_SwapWord (state, +								       temp, +								       state-> +								       Reg +								       [RHSReg]); +					if (temp & 3) +						DEST = ARMul_Align (state, +								    temp, +								    dest); +					else +						DEST = dest; +					if (state->abortSig || state->Aborted) +						TAKEABORT; +				} +				else if ((BITS (0, 11) == 0) && (LHSReg == 15)) {	/* MRS CPSR */ +					UNDEF_MRSPC; +					DEST = ECC | EINT | EMODE; +				} +				else { +					UNDEF_Test; +				} +				break; + +			case 0x11:	/* TSTP reg */ +#ifdef MODET +				if ((BITS (4, 11) & 0xF9) == 0x9) +					/* LDR register offset, no write-back, down, pre indexed.  */ +					LHPREDOWN (); +				/* Continue with remaining instruction decode.  */ +#endif +				if (DESTReg == 15) { +					/* TSTP reg */ +#ifdef MODE32 +					//chy 2006-02-15 if in user mode, can not set cpsr 0:23 +					//from p165 of ARMARM book +					state->Cpsr = GETSPSR (state->Bank); +					ARMul_CPSRAltered (state); +#else +					rhs = DPRegRHS; +					temp = LHS & rhs; +					SETR15PSR (temp); +#endif +				} +				else { +					/* TST reg */ +					rhs = DPSRegRHS; +					dest = LHS & rhs; +					ARMul_NegZero (state, dest); +				} +				break; + +			case 0x12:	/* TEQ reg and MSR reg to CPSR (ARM6).  */ + +				if (state->is_v5) { +					if (BITS (4, 7) == 3) { +						/* BLX(2) */ +						ARMword temp; + +						if (TFLAG) +							temp = (pc + 2) | 1; +						else +							temp = pc + 4; + +						WriteR15Branch (state, +								state-> +								Reg[RHSReg]); +						state->Reg[14] = temp; +						break; +					} +				} + +				if (state->is_v5e) { +					if (BIT (4) == 0 && BIT (7) == 1 +					    && (BIT (5) == 0 +						|| BITS (12, 15) == 0)) { +						/* ElSegundo SMLAWy/SMULWy insn.  */ +						unsigned long long op1 = +							state-> +							Reg[BITS (0, 3)]; +						unsigned long long op2 = +							state-> +							Reg[BITS (8, 11)]; +						unsigned long long result; + +						if (BIT (6)) +							op2 >>= 16; +						if (op1 & 0x80000000) +							op1 -= 1ULL << 32; +						op2 &= 0xFFFF; +						if (op2 & 0x8000) +							op2 -= 65536; +						result = (op1 * op2) >> 16; + +						if (BIT (5) == 0) { +							ARMword Rn = +								state-> +								Reg[BITS +								    (12, 15)]; + +							if (AddOverflow +							    (result, Rn, +							     result + Rn)) +								SETS; +							result += Rn; +						} +						state->Reg[BITS (16, 19)] = +							result; +						break; +					} + +					if (BITS (4, 11) == 5) { +						/* ElSegundo QSUB insn.  */ +						ARMword op1 = +							state-> +							Reg[BITS (0, 3)]; +						ARMword op2 = +							state-> +							Reg[BITS (16, 19)]; +						ARMword result = op1 - op2; + +						if (SubOverflow +						    (op1, op2, result)) { +							result = POS (result) +								? 0x80000000 : +								0x7fffffff; +							SETS; +						} + +						state->Reg[BITS (12, 15)] = +							result; +						break; +					} +				} +#ifdef MODET +				if (BITS (4, 11) == 0xB) { +					/* STRH register offset, write-back, down, pre indexed.  */ +					SHPREDOWNWB (); +					break; +				} +				if (BITS (4, 27) == 0x12FFF1) { +					/* BX */ +					WriteR15Branch (state, +							state->Reg[RHSReg]); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +#endif +				if (state->is_v5) { +					if (BITS (4, 7) == 0x7) { +						ARMword value; +						extern int +							SWI_vector_installed; + +						/* Hardware is allowed to optionally override this +						   instruction and treat it as a breakpoint.  Since +						   this is a simulator not hardware, we take the position +						   that if a SWI vector was not installed, then an Abort +						   vector was probably not installed either, and so +						   normally this instruction would be ignored, even if an +						   Abort is generated.  This is a bad thing, since GDB +						   uses this instruction for its breakpoints (at least in +						   Thumb mode it does).  So intercept the instruction here +						   and generate a breakpoint SWI instead.  */ +						if (!SWI_vector_installed) +							ARMul_OSHandleSWI +								(state, +								 SWI_Breakpoint); +						else { +							/* BKPT - normally this will cause an abort, but on the +							   XScale we must check the DCSR.  */ +							XScale_set_fsr_far +								(state, +								 ARMul_CP15_R5_MMU_EXCPT, +								 pc); +							if (!XScale_debug_moe +							    (state, +							     ARMul_CP14_R10_MOE_BT)) +								break; +						} + +						/* Force the next instruction to be refetched.  */ +						state->NextInstr = RESUME; +						break; +					} +				} +				if (DESTReg == 15) { +					/* MSR reg to CPSR.  */ +					UNDEF_MSRPC; +					temp = DPRegRHS; +#ifdef MODET +					/* Don't allow TBIT to be set by MSR.  */ +					temp &= ~TBIT; +#endif +					ARMul_FixCPSR (state, instr, temp); +				} +				else +					UNDEF_Test; + +				break; + +			case 0x13:	/* TEQP reg */ +#ifdef MODET +				if ((BITS (4, 11) & 0xF9) == 0x9) +					/* LDR register offset, write-back, down, pre indexed.  */ +					LHPREDOWNWB (); +				/* Continue with remaining instruction decode.  */ +#endif +				if (DESTReg == 15) { +					/* TEQP reg */ +#ifdef MODE32 +					state->Cpsr = GETSPSR (state->Bank); +					ARMul_CPSRAltered (state); +#else +					rhs = DPRegRHS; +					temp = LHS ^ rhs; +					SETR15PSR (temp); +#endif +				} +				else { +					/* TEQ Reg.  */ +					rhs = DPSRegRHS; +					dest = LHS ^ rhs; +					ARMul_NegZero (state, dest); +				} +				break; + +			case 0x14:	/* CMP reg and MRS SPSR and SWP byte.  */ +				if (state->is_v5e) { +					if (BIT (4) == 0 && BIT (7) == 1) { +						/* ElSegundo SMLALxy insn.  */ +						unsigned long long op1 = +							state-> +							Reg[BITS (0, 3)]; +						unsigned long long op2 = +							state-> +							Reg[BITS (8, 11)]; +						unsigned long long dest; +						unsigned long long result; + +						if (BIT (5)) +							op1 >>= 16; +						if (BIT (6)) +							op2 >>= 16; +						op1 &= 0xFFFF; +						if (op1 & 0x8000) +							op1 -= 65536; +						op2 &= 0xFFFF; +						if (op2 & 0x8000) +							op2 -= 65536; + +						dest = (unsigned long long) +							state-> +							Reg[BITS (16, 19)] << +							32; +						dest |= state-> +							Reg[BITS (12, 15)]; +						dest += op1 * op2; +						state->Reg[BITS (12, 15)] = +							dest; +						state->Reg[BITS (16, 19)] = +							dest >> 32; +						break; +					} + +					if (BITS (4, 11) == 5) { +						/* ElSegundo QDADD insn.  */ +						ARMword op1 = +							state-> +							Reg[BITS (0, 3)]; +						ARMword op2 = +							state-> +							Reg[BITS (16, 19)]; +						ARMword op2d = op2 + op2; +						ARMword result; + +						if (AddOverflow +						    (op2, op2, op2d)) { +							SETS; +							op2d = POS (op2d) ? +								0x80000000 : +								0x7fffffff; +						} + +						result = op1 + op2d; +						if (AddOverflow +						    (op1, op2d, result)) { +							SETS; +							result = POS (result) +								? 0x80000000 : +								0x7fffffff; +						} + +						state->Reg[BITS (12, 15)] = +							result; +						break; +					} +				} +#ifdef MODET +				if (BITS (4, 7) == 0xB) { +					/* STRH immediate offset, no write-back, down, pre indexed.  */ +					SHPREDOWN (); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +#endif +				if (BITS (4, 11) == 9) { +					/* SWP */ +					UNDEF_SWPPC; +					temp = LHS; +					BUSUSEDINCPCS; +#ifndef MODE32 +					if (VECTORACCESS (temp) +					    || ADDREXCEPT (temp)) { +						INTERNALABORT (temp); +						(void) ARMul_LoadByte (state, +								       temp); +						(void) ARMul_LoadByte (state, +								       temp); +					} +					else +#endif +						DEST = ARMul_SwapByte (state, +								       temp, +								       state-> +								       Reg +								       [RHSReg]); +					if (state->abortSig || state->Aborted) +						TAKEABORT; +				} +				else if ((BITS (0, 11) == 0) +					 && (LHSReg == 15)) { +					/* MRS SPSR */ +					UNDEF_MRSPC; +					DEST = GETSPSR (state->Bank); +				} +				else +					UNDEF_Test; + +				break; + +			case 0x15:	/* CMPP reg.  */ +#ifdef MODET +				if ((BITS (4, 7) & 0x9) == 0x9) +					/* LDR immediate offset, no write-back, down, pre indexed.  */ +					LHPREDOWN (); +				/* Continue with remaining instruction decode.  */ +#endif +				if (DESTReg == 15) { +					/* CMPP reg.  */ +#ifdef MODE32 +					state->Cpsr = GETSPSR (state->Bank); +					ARMul_CPSRAltered (state); +#else +					rhs = DPRegRHS; +					temp = LHS - rhs; +					SETR15PSR (temp); +#endif +				} +				else { +					/* CMP reg.  */ +					lhs = LHS; +					rhs = DPRegRHS; +					dest = lhs - rhs; +					ARMul_NegZero (state, dest); +					if ((lhs >= rhs) +					    || ((rhs | lhs) >> 31)) { +						ARMul_SubCarry (state, lhs, +								rhs, dest); +						ARMul_SubOverflow (state, lhs, +								   rhs, dest); +					} +					else { +						CLEARC; +						CLEARV; +					} +				} +				break; + +			case 0x16:	/* CMN reg and MSR reg to SPSR */ +				if (state->is_v5e) { +					if (BIT (4) == 0 && BIT (7) == 1 +					    && BITS (12, 15) == 0) { +						/* ElSegundo SMULxy insn.  */ +						ARMword op1 = +							state-> +							Reg[BITS (0, 3)]; +						ARMword op2 = +							state-> +							Reg[BITS (8, 11)]; +						ARMword Rn = +							state-> +							Reg[BITS (12, 15)]; + +						if (BIT (5)) +							op1 >>= 16; +						if (BIT (6)) +							op2 >>= 16; +						op1 &= 0xFFFF; +						op2 &= 0xFFFF; +						if (op1 & 0x8000) +							op1 -= 65536; +						if (op2 & 0x8000) +							op2 -= 65536; + +						state->Reg[BITS (16, 19)] = +							op1 * op2; +						break; +					} + +					if (BITS (4, 11) == 5) { +						/* ElSegundo QDSUB insn.  */ +						ARMword op1 = +							state-> +							Reg[BITS (0, 3)]; +						ARMword op2 = +							state-> +							Reg[BITS (16, 19)]; +						ARMword op2d = op2 + op2; +						ARMword result; + +						if (AddOverflow +						    (op2, op2, op2d)) { +							SETS; +							op2d = POS (op2d) ? +								0x80000000 : +								0x7fffffff; +						} + +						result = op1 - op2d; +						if (SubOverflow +						    (op1, op2d, result)) { +							SETS; +							result = POS (result) +								? 0x80000000 : +								0x7fffffff; +						} + +						state->Reg[BITS (12, 15)] = +							result; +						break; +					} +				} + +				if (state->is_v5) { +					if (BITS (4, 11) == 0xF1 +					    && BITS (16, 19) == 0xF) { +						/* ARM5 CLZ insn.  */ +						ARMword op1 = +							state-> +							Reg[BITS (0, 3)]; +						int result = 32; + +						if (op1) +							for (result = 0; +							     (op1 & +							      0x80000000) == +							     0; op1 <<= 1) +								result++; +						state->Reg[BITS (12, 15)] = +							result; +						break; +					} +				} + +#ifdef MODET +				if (BITS (4, 7) == 0xB) { +					/* STRH immediate offset, write-back, down, pre indexed.  */ +					SHPREDOWNWB (); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +#endif +				if (DESTReg == 15) { +					/* MSR */ +					UNDEF_MSRPC; +					ARMul_FixSPSR (state, instr, +						       DPRegRHS); +				} +				else { +					UNDEF_Test; +				} +				break; + +			case 0x17:	/* CMNP reg */ +#ifdef MODET +				if ((BITS (4, 7) & 0x9) == 0x9) +					/* LDR immediate offset, write-back, down, pre indexed.  */ +					LHPREDOWNWB (); +				/* Continue with remaining instruction decoding.  */ +#endif +				if (DESTReg == 15) { +#ifdef MODE32 +					state->Cpsr = GETSPSR (state->Bank); +					ARMul_CPSRAltered (state); +#else +					rhs = DPRegRHS; +					temp = LHS + rhs; +					SETR15PSR (temp); +#endif +					break; +				} +				else { +					/* CMN reg.  */ +					lhs = LHS; +					rhs = DPRegRHS; +					dest = lhs + rhs; +					ASSIGNZ (dest == 0); +					if ((lhs | rhs) >> 30) { +						/* Possible C,V,N to set.  */ +						ASSIGNN (NEG (dest)); +						ARMul_AddCarry (state, lhs, +								rhs, dest); +						ARMul_AddOverflow (state, lhs, +								   rhs, dest); +					} +					else { +						CLEARN; +						CLEARC; +						CLEARV; +					} +				} +				break; + +			case 0x18:	/* ORR reg */ +#ifdef MODET +				/* dyf add armv6 instr strex  2010.9.17 */ +				if (state->is_v6) { +					if (BITS (4, 7) == 0x9) +						if (handle_v6_insn (state, instr)) +							break; +				} + +				if (BITS (4, 11) == 0xB) { +					/* STRH register offset, no write-back, up, pre indexed.  */ +					SHPREUP (); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +#endif +				rhs = DPRegRHS; +				dest = LHS | rhs; +				WRITEDEST (dest); +				break; + +			case 0x19:	/* ORRS reg */ +#ifdef MODET +				/* dyf add armv6 instr ldrex */ +				if (state->is_v6) { +					if (BITS (4, 7) == 0x9) { +						if (handle_v6_insn (state, instr)) +							break; +					} +				} +				if ((BITS (4, 11) & 0xF9) == 0x9) +					/* LDR register offset, no write-back, up, pre indexed.  */ +					LHPREUP (); +				/* Continue with remaining instruction decoding.  */ +#endif +				rhs = DPSRegRHS; +				dest = LHS | rhs; +				WRITESDEST (dest); +				break; + +			case 0x1a:	/* MOV reg */ +#ifdef MODET +				if (BITS (4, 11) == 0xB) { +					/* STRH register offset, write-back, up, pre indexed.  */ +					SHPREUPWB (); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +#endif +				dest = DPRegRHS; +				WRITEDEST (dest); +				break; + +			case 0x1b:	/* MOVS reg */ +#ifdef MODET +				if ((BITS (4, 11) & 0xF9) == 0x9) +					/* LDR register offset, write-back, up, pre indexed.  */ +					LHPREUPWB (); +				/* Continue with remaining instruction decoding.  */ +#endif +				dest = DPSRegRHS; +				WRITESDEST (dest); +				break; + +			case 0x1c:	/* BIC reg */ +#ifdef MODET +				/* dyf add for STREXB */ +				if (state->is_v6) { +					if (BITS (4, 7) == 0x9) { +						if (handle_v6_insn (state, instr)) +							break; +					} +				} +				if (BITS (4, 7) == 0xB) { +					/* STRH immediate offset, no write-back, up, pre indexed.  */ +					SHPREUP (); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				else if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +#endif +				rhs = DPRegRHS; +				dest = LHS & ~rhs; +				WRITEDEST (dest); +				break; + +			case 0x1d:	/* BICS reg */ +#ifdef MODET +				/* ladsh P=1 U=1 W=0 L=1 S=1 H=1 */ +				if (BITS(4, 7) == 0xF) { +					temp = LHS + GetLS7RHS (state, instr); +					LoadHalfWord (state, instr, temp, LSIGNED); +					break; + +				} +				if (BITS (4, 7) == 0xb) { +					/* LDRH immediate offset, no write-back, up, pre indexed.  */ +					temp = LHS + GetLS7RHS (state, instr); +					LoadHalfWord (state, instr, temp, LUNSIGNED); +					break; +				} +				if (BITS (4, 7) == 0xd) { +					// alex-ykl fix: 2011-07-20 missing ldrsb instruction +					temp = LHS + GetLS7RHS (state, instr); +					LoadByte (state, instr, temp, LSIGNED); +					break; +				} + +				/* Continue with instruction decoding.  */ +				/*if ((BITS (4, 7) & 0x9) == 0x9) */ +				if ((BITS (4, 7)) == 0x9) { +					/* ldrexb */ +					if (state->is_v6) { +						if (handle_v6_insn (state, instr)) +							break; +					} +					/* LDR immediate offset, no write-back, up, pre indexed.  */ +					LHPREUP (); + +				} + +#endif +				rhs = DPSRegRHS; +				dest = LHS & ~rhs; +				WRITESDEST (dest); +				break; + +			case 0x1e:	/* MVN reg */ +#ifdef MODET +				if (BITS (4, 7) == 0xB) { +					/* STRH immediate offset, write-back, up, pre indexed.  */ +					SHPREUPWB (); +					break; +				} +				if (BITS (4, 7) == 0xD) { +					Handle_Load_Double (state, instr); +					break; +				} +				if (BITS (4, 7) == 0xF) { +					Handle_Store_Double (state, instr); +					break; +				} +#endif +				dest = ~DPRegRHS; +				WRITEDEST (dest); +				break; + +			case 0x1f:	/* MVNS reg */ +#ifdef MODET +				if ((BITS (4, 7) & 0x9) == 0x9) +					/* LDR immediate offset, write-back, up, pre indexed.  */ +					LHPREUPWB (); +				/* Continue instruction decoding.  */ +#endif +				dest = ~DPSRegRHS; +				WRITESDEST (dest); +				break; + + +				/* Data Processing Immediate RHS Instructions.  */ + +			case 0x20:	/* AND immed */ +				dest = LHS & DPImmRHS; +				WRITEDEST (dest); +				break; + +			case 0x21:	/* ANDS immed */ +				DPSImmRHS; +				dest = LHS & rhs; +				WRITESDEST (dest); +				break; + +			case 0x22:	/* EOR immed */ +				dest = LHS ^ DPImmRHS; +				WRITEDEST (dest); +				break; + +			case 0x23:	/* EORS immed */ +				DPSImmRHS; +				dest = LHS ^ rhs; +				WRITESDEST (dest); +				break; + +			case 0x24:	/* SUB immed */ +				dest = LHS - DPImmRHS; +				WRITEDEST (dest); +				break; + +			case 0x25:	/* SUBS immed */ +				lhs = LHS; +				rhs = DPImmRHS; +				dest = lhs - rhs; + +				if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { +					ARMul_SubCarry (state, lhs, rhs, +							dest); +					ARMul_SubOverflow (state, lhs, rhs, +							   dest); +				} +				else { +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x26:	/* RSB immed */ +				dest = DPImmRHS - LHS; +				WRITEDEST (dest); +				break; + +			case 0x27:	/* RSBS immed */ +				lhs = LHS; +				rhs = DPImmRHS; +				dest = rhs - lhs; + +				if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { +					ARMul_SubCarry (state, rhs, lhs, +							dest); +					ARMul_SubOverflow (state, rhs, lhs, +							   dest); +				} +				else { +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x28:	/* ADD immed */ +				dest = LHS + DPImmRHS; +				WRITEDEST (dest); +				break; + +			case 0x29:	/* ADDS immed */ +				lhs = LHS; +				rhs = DPImmRHS; +				dest = lhs + rhs; +				ASSIGNZ (dest == 0); + +				if ((lhs | rhs) >> 30) { +					/* Possible C,V,N to set.  */ +					ASSIGNN (NEG (dest)); +					ARMul_AddCarry (state, lhs, rhs, +							dest); +					ARMul_AddOverflow (state, lhs, rhs, +							   dest); +				} +				else { +					CLEARN; +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x2a:	/* ADC immed */ +				dest = LHS + DPImmRHS + CFLAG; +				WRITEDEST (dest); +				break; + +			case 0x2b:	/* ADCS immed */ +				lhs = LHS; +				rhs = DPImmRHS; +				dest = lhs + rhs + CFLAG; +				ASSIGNZ (dest == 0); +				if ((lhs | rhs) >> 30) { +					/* Possible C,V,N to set.  */ +					ASSIGNN (NEG (dest)); +					ARMul_AddCarry (state, lhs, rhs, +							dest); +					ARMul_AddOverflow (state, lhs, rhs, +							   dest); +				} +				else { +					CLEARN; +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x2c:	/* SBC immed */ +				dest = LHS - DPImmRHS - !CFLAG; +				WRITEDEST (dest); +				break; + +			case 0x2d:	/* SBCS immed */ +				lhs = LHS; +				rhs = DPImmRHS; +				dest = lhs - rhs - !CFLAG; +				if ((lhs >= rhs) || ((rhs | lhs) >> 31)) { +					ARMul_SubCarry (state, lhs, rhs, +							dest); +					ARMul_SubOverflow (state, lhs, rhs, +							   dest); +				} +				else { +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x2e:	/* RSC immed */ +				dest = DPImmRHS - LHS - !CFLAG; +				WRITEDEST (dest); +				break; + +			case 0x2f:	/* RSCS immed */ +				lhs = LHS; +				rhs = DPImmRHS; +				dest = rhs - lhs - !CFLAG; +				if ((rhs >= lhs) || ((rhs | lhs) >> 31)) { +					ARMul_SubCarry (state, rhs, lhs, +							dest); +					ARMul_SubOverflow (state, rhs, lhs, +							   dest); +				} +				else { +					CLEARC; +					CLEARV; +				} +				WRITESDEST (dest); +				break; + +			case 0x30:	/* TST immed */ +				/* shenoubang 2012-3-14*/ +				if (state->is_v6) { /* movw, ARMV6, ARMv7 */ +					dest ^= dest; +					dest = BITS(16, 19); +					dest = ((dest<<12) | BITS(0, 11)); +					WRITEDEST(dest); +					//SKYEYE_DBG("In %s, line = %d, pc = 0x%x, instr = 0x%x, R[0:11]: 0x%x, R[16:19]: 0x%x, R[%d]:0x%x\n", +					//		__func__, __LINE__, pc, instr, BITS(0, 11), BITS(16, 19), DESTReg, state->Reg[DESTReg]); +					break; +				} +				else { +					UNDEF_Test; +					break; +				} + +			case 0x31:	/* TSTP immed */ +				if (DESTReg == 15) { +					/* TSTP immed.  */ +#ifdef MODE32 +					state->Cpsr = GETSPSR (state->Bank); +					ARMul_CPSRAltered (state); +#else +					temp = LHS & DPImmRHS; +					SETR15PSR (temp); +#endif +				} +				else { +					/* TST immed.  */ +					DPSImmRHS; +					dest = LHS & rhs; +					ARMul_NegZero (state, dest); +				} +				break; + +			case 0x32:	/* TEQ immed and MSR immed to CPSR */ +				if (DESTReg == 15) +					/* MSR immed to CPSR.  */ +					ARMul_FixCPSR (state, instr, +						       DPImmRHS); +				else +					UNDEF_Test; +				break; + +			case 0x33:	/* TEQP immed */ +				if (DESTReg == 15) { +					/* TEQP immed.  */ +#ifdef MODE32 +					state->Cpsr = GETSPSR (state->Bank); +					ARMul_CPSRAltered (state); +#else +					temp = LHS ^ DPImmRHS; +					SETR15PSR (temp); +#endif +				} +				else { +					DPSImmRHS;	/* TEQ immed */ +					dest = LHS ^ rhs; +					ARMul_NegZero (state, dest); +				} +				break; + +			case 0x34:	/* CMP immed */ +				UNDEF_Test; +				break; + +			case 0x35:	/* CMPP immed */ +				if (DESTReg == 15) { +					/* CMPP immed.  */ +#ifdef MODE32 +					state->Cpsr = GETSPSR (state->Bank); +					ARMul_CPSRAltered (state); +#else +					temp = LHS - DPImmRHS; +					SETR15PSR (temp); +#endif +					break; +				} +				else { +					/* CMP immed.  */ +					lhs = LHS; +					rhs = DPImmRHS; +					dest = lhs - rhs; +					ARMul_NegZero (state, dest); + +					if ((lhs >= rhs) +					    || ((rhs | lhs) >> 31)) { +						ARMul_SubCarry (state, lhs, +								rhs, dest); +						ARMul_SubOverflow (state, lhs, +								   rhs, dest); +					} +					else { +						CLEARC; +						CLEARV; +					} +				} +				break; + +			case 0x36:	/* CMN immed and MSR immed to SPSR */ +				if (DESTReg == 15) +					ARMul_FixSPSR (state, instr, +						       DPImmRHS); +				else +					UNDEF_Test; +				break; + +			case 0x37:	/* CMNP immed.  */ +				if (DESTReg == 15) { +					/* CMNP immed.  */ +#ifdef MODE32 +					state->Cpsr = GETSPSR (state->Bank); +					ARMul_CPSRAltered (state); +#else +					temp = LHS + DPImmRHS; +					SETR15PSR (temp); +#endif +					break; +				} +				else { +					/* CMN immed.  */ +					lhs = LHS; +					rhs = DPImmRHS; +					dest = lhs + rhs; +					ASSIGNZ (dest == 0); +					if ((lhs | rhs) >> 30) { +						/* Possible C,V,N to set.  */ +						ASSIGNN (NEG (dest)); +						ARMul_AddCarry (state, lhs, +								rhs, dest); +						ARMul_AddOverflow (state, lhs, +								   rhs, dest); +					} +					else { +						CLEARN; +						CLEARC; +						CLEARV; +					} +				} +				break; + +			case 0x38:	/* ORR immed.  */ +				dest = LHS | DPImmRHS; +				WRITEDEST (dest); +				break; + +			case 0x39:	/* ORRS immed.  */ +				DPSImmRHS; +				dest = LHS | rhs; +				WRITESDEST (dest); +				break; + +			case 0x3a:	/* MOV immed.  */ +				dest = DPImmRHS; +				WRITEDEST (dest); +				break; + +			case 0x3b:	/* MOVS immed.  */ +				DPSImmRHS; +				WRITESDEST (rhs); +				break; + +			case 0x3c:	/* BIC immed.  */ +				dest = LHS & ~DPImmRHS; +				WRITEDEST (dest); +				break; + +			case 0x3d:	/* BICS immed.  */ +				DPSImmRHS; +				dest = LHS & ~rhs; +				WRITESDEST (dest); +				break; + +			case 0x3e:	/* MVN immed.  */ +				dest = ~DPImmRHS; +				WRITEDEST (dest); +				break; + +			case 0x3f:	/* MVNS immed.  */ +				DPSImmRHS; +				WRITESDEST (~rhs); +				break; + + +				/* Single Data Transfer Immediate RHS Instructions.  */ + +			case 0x40:	/* Store Word, No WriteBack, Post Dec, Immed.  */ +				lhs = LHS; +				if (StoreWord (state, instr, lhs)) +					LSBase = lhs - LSImmRHS; +				break; + +			case 0x41:	/* Load Word, No WriteBack, Post Dec, Immed.  */ +				lhs = LHS; +				if (LoadWord (state, instr, lhs)) +					LSBase = lhs - LSImmRHS; +				break; + +			case 0x42:	/* Store Word, WriteBack, Post Dec, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				lhs = LHS; +				temp = lhs - LSImmRHS; +				state->NtransSig = LOW; +				if (StoreWord (state, instr, lhs)) +					LSBase = temp; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x43:	/* Load Word, WriteBack, Post Dec, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				lhs = LHS; +				state->NtransSig = LOW; +				if (LoadWord (state, instr, lhs)) +					LSBase = lhs - LSImmRHS; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x44:	/* Store Byte, No WriteBack, Post Dec, Immed.  */ +				lhs = LHS; +				if (StoreByte (state, instr, lhs)) +					LSBase = lhs - LSImmRHS; +				break; + +			case 0x45:	/* Load Byte, No WriteBack, Post Dec, Immed.  */ +				lhs = LHS; +				if (LoadByte (state, instr, lhs, LUNSIGNED)) +					LSBase = lhs - LSImmRHS; +				break; + +			case 0x46:	/* Store Byte, WriteBack, Post Dec, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				lhs = LHS; +				state->NtransSig = LOW; +				if (StoreByte (state, instr, lhs)) +					LSBase = lhs - LSImmRHS; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x47:	/* Load Byte, WriteBack, Post Dec, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				lhs = LHS; +				state->NtransSig = LOW; +				if (LoadByte (state, instr, lhs, LUNSIGNED)) +					LSBase = lhs - LSImmRHS; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x48:	/* Store Word, No WriteBack, Post Inc, Immed.  */ +				lhs = LHS; +				if (StoreWord (state, instr, lhs)) +					LSBase = lhs + LSImmRHS; +				break; + +			case 0x49:	/* Load Word, No WriteBack, Post Inc, Immed.  */ +				lhs = LHS; +				if (LoadWord (state, instr, lhs)) +					LSBase = lhs + LSImmRHS; +				break; + +			case 0x4a:	/* Store Word, WriteBack, Post Inc, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				lhs = LHS; +				state->NtransSig = LOW; +				if (StoreWord (state, instr, lhs)) +					LSBase = lhs + LSImmRHS; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x4b:	/* Load Word, WriteBack, Post Inc, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				lhs = LHS; +				state->NtransSig = LOW; +				if (LoadWord (state, instr, lhs)) +					LSBase = lhs + LSImmRHS; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x4c:	/* Store Byte, No WriteBack, Post Inc, Immed.  */ +				lhs = LHS; +				if (StoreByte (state, instr, lhs)) +					LSBase = lhs + LSImmRHS; +				break; + +			case 0x4d:	/* Load Byte, No WriteBack, Post Inc, Immed.  */ +				lhs = LHS; +				if (LoadByte (state, instr, lhs, LUNSIGNED)) +					LSBase = lhs + LSImmRHS; +				break; + +			case 0x4e:	/* Store Byte, WriteBack, Post Inc, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				lhs = LHS; +				state->NtransSig = LOW; +				if (StoreByte (state, instr, lhs)) +					LSBase = lhs + LSImmRHS; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x4f:	/* Load Byte, WriteBack, Post Inc, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				lhs = LHS; +				state->NtransSig = LOW; +				if (LoadByte (state, instr, lhs, LUNSIGNED)) +					LSBase = lhs + LSImmRHS; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + + +			case 0x50:	/* Store Word, No WriteBack, Pre Dec, Immed.  */ +				(void) StoreWord (state, instr, +						  LHS - LSImmRHS); +				break; + +			case 0x51:	/* Load Word, No WriteBack, Pre Dec, Immed.  */ +				(void) LoadWord (state, instr, +						 LHS - LSImmRHS); +				break; + +			case 0x52:	/* Store Word, WriteBack, Pre Dec, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				temp = LHS - LSImmRHS; +				if (StoreWord (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x53:	/* Load Word, WriteBack, Pre Dec, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				temp = LHS - LSImmRHS; +				if (LoadWord (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x54:	/* Store Byte, No WriteBack, Pre Dec, Immed.  */ +				(void) StoreByte (state, instr, +						  LHS - LSImmRHS); +				break; + +			case 0x55:	/* Load Byte, No WriteBack, Pre Dec, Immed.  */ +				(void) LoadByte (state, instr, LHS - LSImmRHS, +						 LUNSIGNED); +				break; + +			case 0x56:	/* Store Byte, WriteBack, Pre Dec, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				temp = LHS - LSImmRHS; +				if (StoreByte (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x57:	/* Load Byte, WriteBack, Pre Dec, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				temp = LHS - LSImmRHS; +				if (LoadByte (state, instr, temp, LUNSIGNED)) +					LSBase = temp; +				break; + +			case 0x58:	/* Store Word, No WriteBack, Pre Inc, Immed.  */ +				(void) StoreWord (state, instr, +						  LHS + LSImmRHS); +				break; + +			case 0x59:	/* Load Word, No WriteBack, Pre Inc, Immed.  */ +				(void) LoadWord (state, instr, +						 LHS + LSImmRHS); +				break; + +			case 0x5a:	/* Store Word, WriteBack, Pre Inc, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				temp = LHS + LSImmRHS; +				if (StoreWord (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x5b:	/* Load Word, WriteBack, Pre Inc, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				temp = LHS + LSImmRHS; +				if (LoadWord (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x5c:	/* Store Byte, No WriteBack, Pre Inc, Immed.  */ +				(void) StoreByte (state, instr, +						  LHS + LSImmRHS); +				break; + +			case 0x5d:	/* Load Byte, No WriteBack, Pre Inc, Immed.  */ +				(void) LoadByte (state, instr, LHS + LSImmRHS, +						 LUNSIGNED); +				break; + +			case 0x5e:	/* Store Byte, WriteBack, Pre Inc, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				temp = LHS + LSImmRHS; +				if (StoreByte (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x5f:	/* Load Byte, WriteBack, Pre Inc, Immed.  */ +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				temp = LHS + LSImmRHS; +				if (LoadByte (state, instr, temp, LUNSIGNED)) +					LSBase = temp; +				break; + + +				/* Single Data Transfer Register RHS Instructions.  */ + +			case 0x60:	/* Store Word, No WriteBack, Post Dec, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				if (StoreWord (state, instr, lhs)) +					LSBase = lhs - LSRegRHS; +				break; + +			case 0x61:	/* Load Word, No WriteBack, Post Dec, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				temp = lhs - LSRegRHS; +				if (LoadWord (state, instr, lhs)) +					LSBase = temp; +				break; + +			case 0x62:	/* Store Word, WriteBack, Post Dec, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +					&& handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				state->NtransSig = LOW; +				if (StoreWord (state, instr, lhs)) +					LSBase = lhs - LSRegRHS; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x63:	/* Load Word, WriteBack, Post Dec, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				temp = lhs - LSRegRHS; +				state->NtransSig = LOW; +				if (LoadWord (state, instr, lhs)) +					LSBase = temp; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x64:	/* Store Byte, No WriteBack, Post Dec, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				if (StoreByte (state, instr, lhs)) +					LSBase = lhs - LSRegRHS; +				break; + +			case 0x65:	/* Load Byte, No WriteBack, Post Dec, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				temp = lhs - LSRegRHS; +				if (LoadByte (state, instr, lhs, LUNSIGNED)) +					LSBase = temp; +				break; + +			case 0x66:	/* Store Byte, WriteBack, Post Dec, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				state->NtransSig = LOW; +				if (StoreByte (state, instr, lhs)) +					LSBase = lhs - LSRegRHS; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x67:	/* Load Byte, WriteBack, Post Dec, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				temp = lhs - LSRegRHS; +				state->NtransSig = LOW; +				if (LoadByte (state, instr, lhs, LUNSIGNED)) +					LSBase = temp; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x68:	/* Store Word, No WriteBack, Post Inc, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				if (StoreWord (state, instr, lhs)) +					LSBase = lhs + LSRegRHS; +				break; + +			case 0x69:	/* Load Word, No WriteBack, Post Inc, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				temp = lhs + LSRegRHS; +				if (LoadWord (state, instr, lhs)) +					LSBase = temp; +				break; + +			case 0x6a:	/* Store Word, WriteBack, Post Inc, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				state->NtransSig = LOW; +				if (StoreWord (state, instr, lhs)) +					LSBase = lhs + LSRegRHS; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x6b:	/* Load Word, WriteBack, Post Inc, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				temp = lhs + LSRegRHS; +				state->NtransSig = LOW; +				if (LoadWord (state, instr, lhs)) +					LSBase = temp; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x6c:	/* Store Byte, No WriteBack, Post Inc, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				if (StoreByte (state, instr, lhs)) +					LSBase = lhs + LSRegRHS; +				break; + +			case 0x6d:	/* Load Byte, No WriteBack, Post Inc, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				temp = lhs + LSRegRHS; +				if (LoadByte (state, instr, lhs, LUNSIGNED)) +					LSBase = temp; +				break; + +			case 0x6e:	/* Store Byte, WriteBack, Post Inc, Reg.  */ +#if 0 +				if (state->is_v6) { +					int Rm = 0; +					/* utxb */ +					if (BITS(15, 19) == 0xf && BITS(4, 7) == 0x7) { + +						Rm = (RHS >> (8 * BITS(10, 11))) & 0xff; +						DEST = Rm; +					} + +				} +#endif +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +					      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				state->NtransSig = LOW; +				if (StoreByte (state, instr, lhs)) +					LSBase = lhs + LSRegRHS; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + +			case 0x6f:	/* Load Byte, WriteBack, Post Inc, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				lhs = LHS; +				temp = lhs + LSRegRHS; +				state->NtransSig = LOW; +				if (LoadByte (state, instr, lhs, LUNSIGNED)) +					LSBase = temp; +				state->NtransSig = +					(state->Mode & 3) ? HIGH : LOW; +				break; + + +			case 0x70:	/* Store Word, No WriteBack, Pre Dec, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				(void) StoreWord (state, instr, +						  LHS - LSRegRHS); +				break; + +			case 0x71:	/* Load Word, No WriteBack, Pre Dec, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				(void) LoadWord (state, instr, +						 LHS - LSRegRHS); +				break; + +			case 0x72:	/* Store Word, WriteBack, Pre Dec, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				temp = LHS - LSRegRHS; +				if (StoreWord (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x73:	/* Load Word, WriteBack, Pre Dec, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				temp = LHS - LSRegRHS; +				if (LoadWord (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x74:	/* Store Byte, No WriteBack, Pre Dec, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				(void) StoreByte (state, instr, +						  LHS - LSRegRHS); +				break; + +			case 0x75:	/* Load Byte, No WriteBack, Pre Dec, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +					&& handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				(void) LoadByte (state, instr, LHS - LSRegRHS, +						 LUNSIGNED); +				break; + +			case 0x76:	/* Store Byte, WriteBack, Pre Dec, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				temp = LHS - LSRegRHS; +				if (StoreByte (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x77:	/* Load Byte, WriteBack, Pre Dec, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				temp = LHS - LSRegRHS; +				if (LoadByte (state, instr, temp, LUNSIGNED)) +					LSBase = temp; +				break; + +			case 0x78:	/* Store Word, No WriteBack, Pre Inc, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				(void) StoreWord (state, instr, +						  LHS + LSRegRHS); +				break; + +			case 0x79:	/* Load Word, No WriteBack, Pre Inc, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				(void) LoadWord (state, instr, +						 LHS + LSRegRHS); +				break; + +			case 0x7a:	/* Store Word, WriteBack, Pre Inc, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				temp = LHS + LSRegRHS; +				if (StoreWord (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x7b:	/* Load Word, WriteBack, Pre Inc, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				temp = LHS + LSRegRHS; +				if (LoadWord (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x7c:	/* Store Byte, No WriteBack, Pre Inc, Reg.  */ +				if (BIT (4)) { +#ifdef MODE32 +				  if (state->is_v6 +				      && handle_v6_insn (state, instr)) +		    			break; +#endif + +					ARMul_UndefInstr (state, instr); +					break; +				} +				(void) StoreByte (state, instr, +						  LHS + LSRegRHS); +				break; + +			case 0x7d:	/* Load Byte, No WriteBack, Pre Inc, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				(void) LoadByte (state, instr, LHS + LSRegRHS, +						 LUNSIGNED); +				break; + +			case 0x7e:	/* Store Byte, WriteBack, Pre Inc, Reg.  */ +				if (BIT (4)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				temp = LHS + LSRegRHS; +				if (StoreByte (state, instr, temp)) +					LSBase = temp; +				break; + +			case 0x7f:	/* Load Byte, WriteBack, Pre Inc, Reg.  */ +				if (BIT (4)) { +					/* Check for the special breakpoint opcode. +					   This value should correspond to the value defined +					   as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h.  */ +					if (BITS (0, 19) == 0xfdefe) { +						if (!ARMul_OSHandleSWI +						    (state, SWI_Breakpoint)) +							ARMul_Abort (state, +								     ARMul_SWIV); +					} +					else +						ARMul_UndefInstr (state, +								  instr); +					break; +				} +				UNDEF_LSRBaseEQOffWb; +				UNDEF_LSRBaseEQDestWb; +				UNDEF_LSRPCBaseWb; +				UNDEF_LSRPCOffWb; +				temp = LHS + LSRegRHS; +				if (LoadByte (state, instr, temp, LUNSIGNED)) +					LSBase = temp; +				break; + + +				/* Multiple Data Transfer Instructions.  */ + +			case 0x80:	/* Store, No WriteBack, Post Dec.  */ +				STOREMULT (instr, LSBase - LSMNumRegs + 4L, +					   0L); +				break; + +			case 0x81:	/* Load, No WriteBack, Post Dec.  */ +				LOADMULT (instr, LSBase - LSMNumRegs + 4L, +					  0L); +				break; + +			case 0x82:	/* Store, WriteBack, Post Dec.  */ +				temp = LSBase - LSMNumRegs; +				STOREMULT (instr, temp + 4L, temp); +				break; + +			case 0x83:	/* Load, WriteBack, Post Dec.  */ +				temp = LSBase - LSMNumRegs; +				LOADMULT (instr, temp + 4L, temp); +				break; + +			case 0x84:	/* Store, Flags, No WriteBack, Post Dec.  */ +				STORESMULT (instr, LSBase - LSMNumRegs + 4L, +					    0L); +				break; + +			case 0x85:	/* Load, Flags, No WriteBack, Post Dec.  */ +				LOADSMULT (instr, LSBase - LSMNumRegs + 4L, +					   0L); +				break; + +			case 0x86:	/* Store, Flags, WriteBack, Post Dec.  */ +				temp = LSBase - LSMNumRegs; +				STORESMULT (instr, temp + 4L, temp); +				break; + +			case 0x87:	/* Load, Flags, WriteBack, Post Dec.  */ +				temp = LSBase - LSMNumRegs; +				LOADSMULT (instr, temp + 4L, temp); +				break; + +			case 0x88:	/* Store, No WriteBack, Post Inc.  */ +				STOREMULT (instr, LSBase, 0L); +				break; + +			case 0x89:	/* Load, No WriteBack, Post Inc.  */ +				LOADMULT (instr, LSBase, 0L); +				break; + +			case 0x8a:	/* Store, WriteBack, Post Inc.  */ +				temp = LSBase; +				STOREMULT (instr, temp, temp + LSMNumRegs); +				break; + +			case 0x8b:	/* Load, WriteBack, Post Inc.  */ +				temp = LSBase; +				LOADMULT (instr, temp, temp + LSMNumRegs); +				break; + +			case 0x8c:	/* Store, Flags, No WriteBack, Post Inc.  */ +				STORESMULT (instr, LSBase, 0L); +				break; + +			case 0x8d:	/* Load, Flags, No WriteBack, Post Inc.  */ +				LOADSMULT (instr, LSBase, 0L); +				break; + +			case 0x8e:	/* Store, Flags, WriteBack, Post Inc.  */ +				temp = LSBase; +				STORESMULT (instr, temp, temp + LSMNumRegs); +				break; + +			case 0x8f:	/* Load, Flags, WriteBack, Post Inc.  */ +				temp = LSBase; +				LOADSMULT (instr, temp, temp + LSMNumRegs); +				break; + +			case 0x90:	/* Store, No WriteBack, Pre Dec.  */ +				STOREMULT (instr, LSBase - LSMNumRegs, 0L); +				break; + +			case 0x91:	/* Load, No WriteBack, Pre Dec.  */ +				LOADMULT (instr, LSBase - LSMNumRegs, 0L); +				break; + +			case 0x92:	/* Store, WriteBack, Pre Dec.  */ +				temp = LSBase - LSMNumRegs; +				STOREMULT (instr, temp, temp); +				break; + +			case 0x93:	/* Load, WriteBack, Pre Dec.  */ +				temp = LSBase - LSMNumRegs; +				LOADMULT (instr, temp, temp); +				break; + +			case 0x94:	/* Store, Flags, No WriteBack, Pre Dec.  */ +				STORESMULT (instr, LSBase - LSMNumRegs, 0L); +				break; + +			case 0x95:	/* Load, Flags, No WriteBack, Pre Dec.  */ +				LOADSMULT (instr, LSBase - LSMNumRegs, 0L); +				break; + +			case 0x96:	/* Store, Flags, WriteBack, Pre Dec.  */ +				temp = LSBase - LSMNumRegs; +				STORESMULT (instr, temp, temp); +				break; + +			case 0x97:	/* Load, Flags, WriteBack, Pre Dec.  */ +				temp = LSBase - LSMNumRegs; +				LOADSMULT (instr, temp, temp); +				break; + +			case 0x98:	/* Store, No WriteBack, Pre Inc.  */ +				STOREMULT (instr, LSBase + 4L, 0L); +				break; + +			case 0x99:	/* Load, No WriteBack, Pre Inc.  */ +				LOADMULT (instr, LSBase + 4L, 0L); +				break; + +			case 0x9a:	/* Store, WriteBack, Pre Inc.  */ +				temp = LSBase; +				STOREMULT (instr, temp + 4L, +					   temp + LSMNumRegs); +				break; + +			case 0x9b:	/* Load, WriteBack, Pre Inc.  */ +				temp = LSBase; +				LOADMULT (instr, temp + 4L, +					  temp + LSMNumRegs); +				break; + +			case 0x9c:	/* Store, Flags, No WriteBack, Pre Inc.  */ +				STORESMULT (instr, LSBase + 4L, 0L); +				break; + +			case 0x9d:	/* Load, Flags, No WriteBack, Pre Inc.  */ +				LOADSMULT (instr, LSBase + 4L, 0L); +				break; + +			case 0x9e:	/* Store, Flags, WriteBack, Pre Inc.  */ +				temp = LSBase; +				STORESMULT (instr, temp + 4L, +					    temp + LSMNumRegs); +				break; + +			case 0x9f:	/* Load, Flags, WriteBack, Pre Inc.  */ +				temp = LSBase; +				LOADSMULT (instr, temp + 4L, +					   temp + LSMNumRegs); +				break; + + +				/* Branch forward.  */ +			case 0xa0: +			case 0xa1: +			case 0xa2: +			case 0xa3: +			case 0xa4: +			case 0xa5: +			case 0xa6: +			case 0xa7: +				state->Reg[15] = pc + 8 + POSBRANCH; +				FLUSHPIPE; +				break; + + +				/* Branch backward.  */ +			case 0xa8: +			case 0xa9: +			case 0xaa: +			case 0xab: +			case 0xac: +			case 0xad: +			case 0xae: +			case 0xaf: +				state->Reg[15] = pc + 8 + NEGBRANCH; +				FLUSHPIPE; +				break; + + +				/* Branch and Link forward.  */ +			case 0xb0: +			case 0xb1: +			case 0xb2: +			case 0xb3: +			case 0xb4: +			case 0xb5: +			case 0xb6: +			case 0xb7: +				/* Put PC into Link.  */ +#ifdef MODE32 +				state->Reg[14] = pc + 4; +#else +				state->Reg[14] = +					(pc + 4) | ECC | ER15INT | EMODE; +#endif +				state->Reg[15] = pc + 8 + POSBRANCH; +				FLUSHPIPE; +				break; + + +				/* Branch and Link backward.  */ +			case 0xb8: +			case 0xb9: +			case 0xba: +			case 0xbb: +			case 0xbc: +			case 0xbd: +			case 0xbe: +			case 0xbf: +				/* Put PC into Link.  */ +#ifdef MODE32 +				state->Reg[14] = pc + 4; +#else +				state->Reg[14] = +					(pc + 4) | ECC | ER15INT | EMODE; +#endif +				state->Reg[15] = pc + 8 + NEGBRANCH; +				FLUSHPIPE; +				break; + + +				/* Co-Processor Data Transfers.  */ +			case 0xc4: +				if (state->is_v5) { +					/* Reading from R15 is UNPREDICTABLE.  */ +					if (BITS (12, 15) == 15 +					    || BITS (16, 19) == 15) +						ARMul_UndefInstr (state, +								  instr); +					/* Is access to coprocessor 0 allowed ?  */ +					else if (!CP_ACCESS_ALLOWED +						 (state, CPNum)) +						ARMul_UndefInstr (state, +								  instr); +					/* Special treatment for XScale coprocessors.  */ +					else if (state->is_XScale) { +						/* Only opcode 0 is supported.  */ +						if (BITS (4, 7) != 0x00) +							ARMul_UndefInstr +								(state, +								 instr); +						/* Only coporcessor 0 is supported.  */ +						else if (CPNum != 0x00) +							ARMul_UndefInstr +								(state, +								 instr); +						/* Only accumulator 0 is supported.  */ +						else if (BITS (0, 3) != 0x00) +							ARMul_UndefInstr +								(state, +								 instr); +						else { +							/* XScale MAR insn.  Move two registers into accumulator.  */ +							state->Accumulator = +								state-> +								Reg[BITS +								    (12, 15)]; +							state->Accumulator += +								(ARMdword) +								state-> +								Reg[BITS +								    (16, +								     19)] << +								32; +						} +					} +					else +					{ +						/* MCRR, ARMv5TE and up */ +						ARMul_MCRR (state, instr, DEST, state->Reg[LHSReg]); +						break; +					} +				} +				/* Drop through.  */ + +			case 0xc0:	/* Store , No WriteBack , Post Dec.  */ +				ARMul_STC (state, instr, LHS); +				break; + +			case 0xc5: +				if (state->is_v5) { +					/* Writes to R15 are UNPREDICATABLE.  */ +					if (DESTReg == 15 || LHSReg == 15) +						ARMul_UndefInstr (state, +								  instr); +					/* Is access to the coprocessor allowed ?  */ +					else if (!CP_ACCESS_ALLOWED +						 (state, CPNum)) +						ARMul_UndefInstr (state, +								  instr); +					/* Special handling for XScale coprcoessors.  */ +					else if (state->is_XScale) { +						/* Only opcode 0 is supported.  */ +						if (BITS (4, 7) != 0x00) +							ARMul_UndefInstr +								(state, +								 instr); +						/* Only coprocessor 0 is supported.  */ +						else if (CPNum != 0x00) +							ARMul_UndefInstr +								(state, +								 instr); +						/* Only accumulator 0 is supported.  */ +						else if (BITS (0, 3) != 0x00) +							ARMul_UndefInstr +								(state, +								 instr); +						else { +							/* XScale MRA insn.  Move accumulator into two registers.  */ +							ARMword t1 = +								(state-> +								 Accumulator +								 >> 32) & 255; + +							if (t1 & 128) +								t1 -= 256; + +							state->Reg[BITS +								   (12, 15)] = +								state-> +								Accumulator; +							state->Reg[BITS +								   (16, 19)] = +								t1; +							break; +						} +					} +					else +					{ +						/* MRRC, ARMv5TE and up */ +						ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg])); +						break; + 					} +				} +				/* Drop through.  */ + +			case 0xc1:	/* Load , No WriteBack , Post Dec.  */ +				ARMul_LDC (state, instr, LHS); +				break; + +			case 0xc2: +			case 0xc6:	/* Store , WriteBack , Post Dec.  */ +				lhs = LHS; +				state->Base = lhs - LSCOff; +				ARMul_STC (state, instr, lhs); +				break; + +			case 0xc3: +			case 0xc7:	/* Load , WriteBack , Post Dec.  */ +				lhs = LHS; +				state->Base = lhs - LSCOff; +				ARMul_LDC (state, instr, lhs); +				break; + +			case 0xc8: +			case 0xcc:	/* Store , No WriteBack , Post Inc.  */ +				ARMul_STC (state, instr, LHS); +				break; + +			case 0xc9: +			case 0xcd:	/* Load , No WriteBack , Post Inc.  */ +				ARMul_LDC (state, instr, LHS); +				break; + +			case 0xca: +			case 0xce:	/* Store , WriteBack , Post Inc.  */ +				lhs = LHS; +				state->Base = lhs + LSCOff; +				ARMul_STC (state, instr, LHS); +				break; + +			case 0xcb: +			case 0xcf:	/* Load , WriteBack , Post Inc.  */ +				lhs = LHS; +				state->Base = lhs + LSCOff; +				ARMul_LDC (state, instr, LHS); +				break; + +			case 0xd0: +			case 0xd4:	/* Store , No WriteBack , Pre Dec.  */ +				ARMul_STC (state, instr, LHS - LSCOff); +				break; + +			case 0xd1: +			case 0xd5:	/* Load , No WriteBack , Pre Dec.  */ +				ARMul_LDC (state, instr, LHS - LSCOff); +				break; + +			case 0xd2: +			case 0xd6:	/* Store , WriteBack , Pre Dec.  */ +				lhs = LHS - LSCOff; +				state->Base = lhs; +				ARMul_STC (state, instr, lhs); +				break; + +			case 0xd3: +			case 0xd7:	/* Load , WriteBack , Pre Dec.  */ +				lhs = LHS - LSCOff; +				state->Base = lhs; +				ARMul_LDC (state, instr, lhs); +				break; + +			case 0xd8: +			case 0xdc:	/* Store , No WriteBack , Pre Inc.  */ +				ARMul_STC (state, instr, LHS + LSCOff); +				break; + +			case 0xd9: +			case 0xdd:	/* Load , No WriteBack , Pre Inc.  */ +				ARMul_LDC (state, instr, LHS + LSCOff); +				break; + +			case 0xda: +			case 0xde:	/* Store , WriteBack , Pre Inc.  */ +				lhs = LHS + LSCOff; +				state->Base = lhs; +				ARMul_STC (state, instr, lhs); +				break; + +			case 0xdb: +			case 0xdf:	/* Load , WriteBack , Pre Inc.  */ +				lhs = LHS + LSCOff; +				state->Base = lhs; +				ARMul_LDC (state, instr, lhs); +				break; + + +				/* Co-Processor Register Transfers (MCR) and Data Ops.  */ + +			case 0xe2: +				if (!CP_ACCESS_ALLOWED (state, CPNum)) { +					ARMul_UndefInstr (state, instr); +					break; +				} +				if (state->is_XScale) +					switch (BITS (18, 19)) { +					case 0x0: +						if (BITS (4, 11) == 1 +						    && BITS (16, 17) == 0) { +							/* XScale MIA instruction.  Signed multiplication of +							   two 32 bit values and addition to 40 bit accumulator.  */ +							long long Rm = +								state-> +								Reg +								[MULLHSReg]; +							long long Rs = +								state-> +								Reg +								[MULACCReg]; + +							if (Rm & (1 << 31)) +								Rm -= 1ULL << +									32; +							if (Rs & (1 << 31)) +								Rs -= 1ULL << +									32; +							state->Accumulator += +								Rm * Rs; +							_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +						} +						break; + +					case 0x2: +						if (BITS (4, 11) == 1 +						    && BITS (16, 17) == 0) { +							/* XScale MIAPH instruction.  */ +							ARMword t1 = +								state-> +								Reg[MULLHSReg] +								>> 16; +							ARMword t2 = +								state-> +								Reg[MULACCReg] +								>> 16; +							ARMword t3 = +								state-> +								Reg[MULLHSReg] +								& 0xffff; +							ARMword t4 = +								state-> +								Reg[MULACCReg] +								& 0xffff; +							long long t5; + +							if (t1 & (1 << 15)) +								t1 -= 1 << 16; +							if (t2 & (1 << 15)) +								t2 -= 1 << 16; +							if (t3 & (1 << 15)) +								t3 -= 1 << 16; +							if (t4 & (1 << 15)) +								t4 -= 1 << 16; +							t1 *= t2; +							t5 = t1; +							if (t5 & (1 << 31)) +								t5 -= 1ULL << +									32; +							state->Accumulator += +								t5; +							t3 *= t4; +							t5 = t3; +							if (t5 & (1 << 31)) +								t5 -= 1ULL << +									32; +							state->Accumulator += +								t5; +							_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +						} +						break; + +					case 0x3: +						if (BITS (4, 11) == 1) { +							/* XScale MIAxy instruction.  */ +							ARMword t1; +							ARMword t2; +							long long t5; + +							if (BIT (17)) +								t1 = state-> +									Reg +									[MULLHSReg] +									>> 16; +							else +								t1 = state-> +									Reg +									[MULLHSReg] +									& +									0xffff; + +							if (BIT (16)) +								t2 = state-> +									Reg +									[MULACCReg] +									>> 16; +							else +								t2 = state-> +									Reg +									[MULACCReg] +									& +									0xffff; + +							if (t1 & (1 << 15)) +								t1 -= 1 << 16; +							if (t2 & (1 << 15)) +								t2 -= 1 << 16; +							t1 *= t2; +							t5 = t1; +							if (t5 & (1 << 31)) +								t5 -= 1ULL << +									32; +							state->Accumulator += +								t5; +							_assert_msg_(ARM11, false, "disabled skyeye code 'goto donext'"); //goto donext; +						} +						break; + +					default: +						break; +					} +				/* Drop through.  */ + +			case 0xe0: +			case 0xe4: +			case 0xe6: +			case 0xe8: +			case 0xea: +			case 0xec: +			case 0xee: +				if (BIT (4)) { +					/* MCR.  */ +					if (DESTReg == 15) { +						UNDEF_MCRPC; +#ifdef MODE32 +						ARMul_MCR (state, instr, +							   state->Reg[15] + +							   isize); +#else +						ARMul_MCR (state, instr, +							   ECC | ER15INT | +							   EMODE | +							   ((state->Reg[15] + +							     isize) & +							    R15PCBITS)); +#endif +					} +					else +						ARMul_MCR (state, instr, +							   DEST); +				} +				else +					/* CDP Part 1.  */ +					ARMul_CDP (state, instr); +				break; + + +				/* Co-Processor Register Transfers (MRC) and Data Ops.  */ +			case 0xe1: +			case 0xe3: +			case 0xe5: +			case 0xe7: +			case 0xe9: +			case 0xeb: +			case 0xed: +			case 0xef: +				if (BIT (4)) { +					/* MRC */ +					temp = ARMul_MRC (state, instr); +					if (DESTReg == 15) { +						ASSIGNN ((temp & NBIT) != 0); +						ASSIGNZ ((temp & ZBIT) != 0); +						ASSIGNC ((temp & CBIT) != 0); +						ASSIGNV ((temp & VBIT) != 0); +					} +					else +						DEST = temp; +				} +				else +					/* CDP Part 2.  */ +					ARMul_CDP (state, instr); +				break; + + +				/* SWI instruction.  */ +			case 0xf0: +			case 0xf1: +			case 0xf2: +			case 0xf3: +			case 0xf4: +			case 0xf5: +			case 0xf6: +			case 0xf7: +			case 0xf8: +			case 0xf9: +			case 0xfa: +			case 0xfb: +			case 0xfc: +			case 0xfd: +			case 0xfe: +			case 0xff: +				if (instr == ARMul_ABORTWORD +				    && state->AbortAddr == pc) { +					/* A prefetch abort.  */ +					XScale_set_fsr_far (state, +							    ARMul_CP15_R5_MMU_EXCPT, +							    pc); +					ARMul_Abort (state, +						     ARMul_PrefetchAbortV); +					break; +				} +				//sky_pref_t* pref = get_skyeye_pref(); +				//if(pref->user_mode_sim){ +				//	ARMul_OSHandleSWI (state, BITS (0, 23)); +				//	break; +				//} +				ARMul_Abort (state, ARMul_SWIV); +				break; +			} +		} +		 +#ifdef MODET +	      donext: +#endif +		      state->pc = pc; +#if 0 +			/* shenoubang */ +			instr_sum++; +			int i, j; +			i = j = 0; +			if (instr_sum >= 7388648) { +			//if (pc == 0xc0008ab4) { +			//	printf("instr_sum: %d\n", instr_sum); +				// start_kernel : 0xc000895c +				printf("--------------------------------------------------\n"); +				for (i = 0; i < 16; i++) { +					printf("[R%02d]:[0x%08x]\t", i, state->Reg[i]); +					if ((i % 3) == 2) { +						printf("\n"); +					} +				} +				printf("[cpr]:[0x%08x]\t[spr0]:[0x%08x]\n", state->Cpsr, state->Spsr[0]); +				for (j = 1; j < 7; j++) { +					printf("[spr%d]:[0x%08x]\t", j, state->Spsr[j]); +					if ((j % 4) == 3) { +						printf("\n"); +					} +				} +				printf("\n[PC]:[0x%08x]\t[INST]:[0x%08x]\t[COUNT]:[%d]\n", pc, instr, instr_sum); +				printf("--------------------------------------------------\n"); +			} +#endif + +#if 0 +		  fprintf(state->state_log, "PC:0x%x\n", pc); +		  for (reg_index = 0; reg_index < 16; reg_index ++) { +				  if (state->Reg[reg_index] != mirror_register_file[reg_index]) { +						  fprintf(state->state_log, "R%d:0x%x\n", reg_index, state->Reg[reg_index]); +						  mirror_register_file[reg_index] = state->Reg[reg_index]; +				  } +		  } +		  if (state->Cpsr != mirror_register_file[CPSR_REG]) { +				  fprintf(state->state_log, "Cpsr:0x%x\n", state->Cpsr); +				  mirror_register_file[CPSR_REG] = state->Cpsr; +		  } +          if (state->RegBank[SVCBANK][13] != mirror_register_file[R13_SVC]) { +                  fprintf(state->state_log, "R13_SVC:0x%x\n", state->RegBank[SVCBANK][13]); +                  mirror_register_file[R13_SVC] = state->RegBank[SVCBANK][13]; +          } +          if (state->RegBank[SVCBANK][14] != mirror_register_file[R14_SVC]) { +                  fprintf(state->state_log, "R14_SVC:0x%x\n", state->RegBank[SVCBANK][14]); +                  mirror_register_file[R14_SVC] = state->RegBank[SVCBANK][14]; +          } +          if (state->RegBank[ABORTBANK][13] != mirror_register_file[R13_ABORT]) { +                  fprintf(state->state_log, "R13_ABORT:0x%x\n", state->RegBank[ABORTBANK][13]); +                  mirror_register_file[R13_ABORT] = state->RegBank[ABORTBANK][13]; +          } +          if (state->RegBank[ABORTBANK][14] != mirror_register_file[R14_ABORT]) { +                  fprintf(state->state_log, "R14_ABORT:0x%x\n", state->RegBank[ABORTBANK][14]); +                  mirror_register_file[R14_ABORT] = state->RegBank[ABORTBANK][14]; +          } +          if (state->RegBank[UNDEFBANK][13] != mirror_register_file[R13_UNDEF]) { +                  fprintf(state->state_log, "R13_UNDEF:0x%x\n", state->RegBank[UNDEFBANK][13]); +                  mirror_register_file[R13_UNDEF] = state->RegBank[UNDEFBANK][13]; +          } +          if (state->RegBank[UNDEFBANK][14] != mirror_register_file[R14_UNDEF]) { +                  fprintf(state->state_log, "R14_UNDEF:0x%x\n", state->RegBank[UNDEFBANK][14]); +                  mirror_register_file[R14_UNDEF] = state->RegBank[UNDEFBANK][14]; +          } +          if (state->RegBank[IRQBANK][13] != mirror_register_file[R13_IRQ]) { +                  fprintf(state->state_log, "R13_IRQ:0x%x\n", state->RegBank[IRQBANK][13]); +                  mirror_register_file[R13_IRQ] = state->RegBank[IRQBANK][13]; +          } +          if (state->RegBank[IRQBANK][14] != mirror_register_file[R14_IRQ]) { +                  fprintf(state->state_log, "R14_IRQ:0x%x\n", state->RegBank[IRQBANK][14]); +                  mirror_register_file[R14_IRQ] = state->RegBank[IRQBANK][14]; +          } +          if (state->RegBank[FIQBANK][8] != mirror_register_file[R8_FIRQ]) { +                  fprintf(state->state_log, "R8_FIRQ:0x%x\n", state->RegBank[FIQBANK][8]); +                  mirror_register_file[R8_FIRQ] = state->RegBank[FIQBANK][8]; +          } +          if (state->RegBank[FIQBANK][9] != mirror_register_file[R9_FIRQ]) { +                  fprintf(state->state_log, "R9_FIRQ:0x%x\n", state->RegBank[FIQBANK][9]); +                  mirror_register_file[R9_FIRQ] = state->RegBank[FIQBANK][9]; +          } +          if (state->RegBank[FIQBANK][10] != mirror_register_file[R10_FIRQ]) { +                  fprintf(state->state_log, "R10_FIRQ:0x%x\n", state->RegBank[FIQBANK][10]); +                  mirror_register_file[R10_FIRQ] = state->RegBank[FIQBANK][10]; +          } +          if (state->RegBank[FIQBANK][11] != mirror_register_file[R11_FIRQ]) { +                  fprintf(state->state_log, "R11_FIRQ:0x%x\n", state->RegBank[FIQBANK][11]); +                  mirror_register_file[R11_FIRQ] = state->RegBank[FIQBANK][11]; +          } +          if (state->RegBank[FIQBANK][12] != mirror_register_file[R12_FIRQ]) { +                  fprintf(state->state_log, "R12_FIRQ:0x%x\n", state->RegBank[FIQBANK][12]); +                  mirror_register_file[R12_FIRQ] = state->RegBank[FIQBANK][12]; +          } +          if (state->RegBank[FIQBANK][13] != mirror_register_file[R13_FIRQ]) { +                  fprintf(state->state_log, "R13_FIRQ:0x%x\n", state->RegBank[FIQBANK][13]); +                  mirror_register_file[R13_FIRQ] = state->RegBank[FIQBANK][13]; +          } +          if (state->RegBank[FIQBANK][14] != mirror_register_file[R14_FIRQ]) { +                  fprintf(state->state_log, "R14_FIRQ:0x%x\n", state->RegBank[FIQBANK][14]); +                  mirror_register_file[R14_FIRQ] = state->RegBank[FIQBANK][14]; +          } +          if (state->Spsr[SVCBANK] != mirror_register_file[SPSR_SVC]) { +                  fprintf(state->state_log, "SPSR_SVC:0x%x\n", state->Spsr[SVCBANK]); +                  mirror_register_file[SPSR_SVC] = state->RegBank[SVCBANK]; +          } +          if (state->Spsr[ABORTBANK] != mirror_register_file[SPSR_ABORT]) { +                  fprintf(state->state_log, "SPSR_ABORT:0x%x\n", state->Spsr[ABORTBANK]); +                  mirror_register_file[SPSR_ABORT] = state->RegBank[ABORTBANK]; +          } +          if (state->Spsr[UNDEFBANK] != mirror_register_file[SPSR_UNDEF]) { +                  fprintf(state->state_log, "SPSR_UNDEF:0x%x\n", state->Spsr[UNDEFBANK]); +                  mirror_register_file[SPSR_UNDEF] = state->RegBank[UNDEFBANK]; +          } +          if (state->Spsr[IRQBANK] != mirror_register_file[SPSR_IRQ]) { +                  fprintf(state->state_log, "SPSR_IRQ:0x%x\n", state->Spsr[IRQBANK]); +                  mirror_register_file[SPSR_IRQ] = state->RegBank[IRQBANK]; +          } +          if (state->Spsr[FIQBANK] != mirror_register_file[SPSR_FIRQ]) { +                  fprintf(state->state_log, "SPSR_FIRQ:0x%x\n", state->Spsr[FIQBANK]); +                  mirror_register_file[SPSR_FIRQ] = state->RegBank[FIQBANK]; +          } + +#endif + +#ifdef NEED_UI_LOOP_HOOK +		if (ui_loop_hook != NULL && ui_loop_hook_counter-- < 0) { +			ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL; +			ui_loop_hook (0); +		} +#endif /* NEED_UI_LOOP_HOOK */ + +		/*added energy_prof statement by ksh in 2004-11-26 */ +		//chy 2005-07-28 for standalone +		//ARMul_do_energy(state,instr,pc); +//teawater add for record reg value to ./reg.txt 2005.07.10--------------------- +		if (state->tea_break_ok && pc == state->tea_break_addr) { +			ARMul_Debug (state, 0, 0); +			state->tea_break_ok = 0; +		} +		else { +			state->tea_break_ok = 1; +		} +//AJ2D-------------------------------------------------------------------------- +//chy 2006-04-14 for ctrl-c debug +#if 0 +   if (debugmode) { +      if (instr != ARMul_ABORTWORD) {  +        remote_interrupt_test_time++; +	//chy 2006-04-14 2000 should be changed in skyeye_conf ???!!! +	if (remote_interrupt_test_time >= 2000) { +           remote_interrupt_test_time=0; +	   if (remote_interrupt()) { +		//for test +		//printf("SKYEYE: ICE_debug recv Ctrl_C\n"); +		state->EndCondition = 0; +		state->Emulate = STOP; +	   } +	} +      } +   } +#endif +		 +		/* jump out every time */ +		//state->EndCondition = 0; +                //state->Emulate = STOP; +//chy 2006-04-12 for ICE debug +TEST_EMULATE: +		if (state->Emulate == ONCE) +			state->Emulate = STOP; +		//chy: 2003-08-23: should not use CHANGEMODE !!!! +		/* If we have changed mode, allow the PC to advance before stopping.  */ +		//    else if (state->Emulate == CHANGEMODE) +		//        continue; +		else if (state->Emulate != RUN) +			break; +	} +	while (!state->stop_simulator); + +	state->decoded = decoded; +	state->loaded = loaded; +	state->pc = pc; +	//chy 2006-04-12, for ICE debug +	state->decoded_addr=decoded_addr; +	state->loaded_addr=loaded_addr; +	 +	return pc; +} + +//teawater add for arm2x86 2005.02.17------------------------------------------- +/*ywc 2005-04-01*/ +//#include "tb.h" +//#include "arm2x86_self.h" + +static volatile void (*gen_func) (void); +//static volatile ARMul_State   *tmp_st; +//static volatile ARMul_State   *save_st; +static volatile uint32_t tmp_st; +static volatile uint32_t save_st; +static volatile uint32_t save_T0; +static volatile uint32_t save_T1; +static volatile uint32_t save_T2; + +#ifdef MODE32 +#ifdef DBCT +//teawater change for debug function 2005.07.09--------------------------------- +ARMword +ARMul_Emulate32_dbct (ARMul_State * state) +{ +	static int init = 0; +	static FILE *fd; + +	/*if (!init) { + +	   fd = fopen("./pc.txt", "w"); +	   if (!fd) { +	   exit(-1); +	   } +	   init = 1; +	   } */ + +	state->Reg[15] += INSN_SIZE; +	do { +		/*if (skyeye_config.log.logon>=1) { +		   if (state->NumInstrs>=skyeye_config.log.start && state->NumInstrs<=skyeye_config.log.end) { +		   static int mybegin=0; +		   static int myinstrnum=0; + +		   if (mybegin==0) mybegin=1; +		   if (mybegin==1) { +		   state->Reg[15] -= INSN_SIZE; +		   if (skyeye_config.log.logon>=1) fprintf(skyeye_logfd,"N %llx :p %x,i %x,",state->NumInstrs, (state->Reg[15] - INSN_SIZE), instr); +		   if (skyeye_config.log.logon>=2) SKYEYE_OUTREGS(skyeye_logfd); +		   if (skyeye_config.log.logon>=3) SKYEYE_OUTMOREREGS(skyeye_logfd); +		   fprintf(skyeye_logfd,"\n"); +		   if (skyeye_config.log.length>0) { +		   myinstrnum++; +		   if (myinstrnum>=skyeye_config.log.length) { +		   myinstrnum=0; +		   fflush(skyeye_logfd); +		   fseek(skyeye_logfd,0L,SEEK_SET); +		   } +		   } +		   state->Reg[15] += INSN_SIZE; +		   } +		   } +		   } */ +		state->trap = 0; +		gen_func = +			(void *) tb_find (state, state->Reg[15] - INSN_SIZE); +		if (!gen_func) { +			//fprintf(stderr, "SKYEYE: tb_find: Error in find the translate block.\n"); +			//exit(-1); +			//TRAP_INSN_ABORT +			//TEA_OUT(printf("\n------------\npc:%x\n", state->Reg[15] - INSN_SIZE)); +			//TEA_OUT(printf("TRAP_INSN_ABORT\n")); +//teawater add for xscale(arm v5) 2005.09.01------------------------------------ +			/*XScale_set_fsr_far(state, ARMul_CP15_R5_MMU_EXCPT, state->Reg[15] - INSN_SIZE); +			   state->Reg[15] += INSN_SIZE; +			   ARMul_Abort(state, ARMul_PrefetchAbortV); +			   state->Reg[15] += INSN_SIZE; +			   goto next; */ +			state->trap = TRAP_INSN_ABORT; +			goto check; +//AJ2D-------------------------------------------------------------------------- +		} + +		save_st = (uint32_t) st; +		save_T0 = T0; +		save_T1 = T1; +		save_T2 = T2; +		tmp_st = (uint32_t) state; +		wmb (); +		st = (ARMul_State *) tmp_st; +		gen_func (); +		st = (ARMul_State *) save_st; +		T0 = save_T0; +		T1 = save_T1; +		T2 = save_T2; + +		/*if (state->trap != TRAP_OUT) { +		   state->tea_break_ok = 1; +		   } +		   if (state->trap <= TRAP_SET_R15) { +		   goto next; +		   } */ +		//TEA_OUT(printf("\n------------\npc:%x\n", state->Reg[15] - INSN_SIZE)); +//teawater add check thumb 2005.07.21------------------------------------------- +		/*if (TFLAG) { +		   state->Reg[15] -= 2; +		   return(state->Reg[15]); +		   } */ +//AJ2D-------------------------------------------------------------------------- + +//teawater add for xscale(arm v5) 2005.09.01------------------------------------ +	      check: +//AJ2D-------------------------------------------------------------------------- +		switch (state->trap) { +		case TRAP_RESET: +			{ +				//TEA_OUT(printf("TRAP_RESET\n")); +				ARMul_Abort (state, ARMul_ResetV); +				state->Reg[15] += INSN_SIZE; +			} +			break; +		case TRAP_UNPREDICTABLE: +			{ +				ARMul_Debug (state, 0, 0); +			} +			break; +		case TRAP_INSN_UNDEF: +			{ +				//TEA_OUT(printf("TRAP_INSN_UNDEF\n")); +				state->Reg[15] += INSN_SIZE; +				ARMul_UndefInstr (state, 0); +				state->Reg[15] += INSN_SIZE; +			} +			break; +		case TRAP_SWI: +			{ +				//TEA_OUT(printf("TRAP_SWI\n")); +				state->Reg[15] += INSN_SIZE; +				ARMul_Abort (state, ARMul_SWIV); +				state->Reg[15] += INSN_SIZE; +			} +			break; +//teawater add for xscale(arm v5) 2005.09.01------------------------------------ +		case TRAP_INSN_ABORT: +			{ +				XScale_set_fsr_far (state, +						    ARMul_CP15_R5_MMU_EXCPT, +						    state->Reg[15] - +						    INSN_SIZE); +				state->Reg[15] += INSN_SIZE; +				ARMul_Abort (state, ARMul_PrefetchAbortV); +				state->Reg[15] += INSN_SIZE; +			} +			break; +//AJ2D-------------------------------------------------------------------------- +		case TRAP_DATA_ABORT: +			{ +				//TEA_OUT(printf("TRAP_DATA_ABORT\n")); +				state->Reg[15] += INSN_SIZE; +				ARMul_Abort (state, ARMul_DataAbortV); +				state->Reg[15] += INSN_SIZE; +			} +			break; +		case TRAP_IRQ: +			{ +				//TEA_OUT(printf("TRAP_IRQ\n")); +				state->Reg[15] += INSN_SIZE; +				ARMul_Abort (state, ARMul_IRQV); +				state->Reg[15] += INSN_SIZE; +			} +			break; +		case TRAP_FIQ: +			{ +				//TEA_OUT(printf("TRAP_FIQ\n")); +				state->Reg[15] += INSN_SIZE; +				ARMul_Abort (state, ARMul_FIQV); +				state->Reg[15] += INSN_SIZE; +			} +			break; +		case TRAP_SETS_R15: +			{ +				//TEA_OUT(printf("TRAP_SETS_R15\n")); +				/*if (state->Bank > 0) { +				   state->Cpsr = state->Spsr[state->Bank]; +				   ARMul_CPSRAltered (state); +				   } */ +				WriteSR15 (state, state->Reg[15]); +			} +			break; +		case TRAP_SET_CPSR: +			{ +				//TEA_OUT(printf("TRAP_SET_CPSR\n")); +	                       //chy 2006-02-15 USERBANK=SYSTEMBANK=0 +			       //chy 2006-02-16 should use Mode to test +				//if (state->Bank > 0) { +	                        if (state->Mode != USER26MODE && state->Mode != USER32MODE){ +					ARMul_CPSRAltered (state); +				} +				state->Reg[15] += INSN_SIZE; +			} +			break; +		case TRAP_OUT: +			{ +				//TEA_OUT(printf("TRAP_OUT\n")); +				goto out; +			} +			break; +		case TRAP_BREAKPOINT: +			{ +				//TEA_OUT(printf("TRAP_BREAKPOINT\n")); +				state->Reg[15] -= INSN_SIZE; +				if (!ARMul_OSHandleSWI +				    (state, SWI_Breakpoint)) { +					ARMul_Abort (state, ARMul_SWIV); +				} +				state->Reg[15] += INSN_SIZE; +			} +			break; +		} + +	      next: +		if (state->Emulate == ONCE) { +			state->Emulate = STOP; +			break; +		} +		else if (state->Emulate != RUN) { +			break; +		} +	} +	while (!state->stop_simulator); + +      out: +	state->Reg[15] -= INSN_SIZE; +	return (state->Reg[15]); +} +#endif +//AJ2D-------------------------------------------------------------------------- +#endif +//AJ2D-------------------------------------------------------------------------- + +/* This routine evaluates most Data Processing register RHS's with the S +   bit clear.  It is intended to be called from the macro DPRegRHS, which +   filters the common case of an unshifted register with in line code.  */ + +static ARMword +GetDPRegRHS (ARMul_State * state, ARMword instr) +{ +	ARMword shamt, base; + +	base = RHSReg; +	if (BIT (4)) { +		/* Shift amount in a register.  */ +		UNDEF_Shift; +		INCPC; +#ifndef MODE32 +		if (base == 15) +			base = ECC | ER15INT | R15PC | EMODE; +		else +#endif +			base = state->Reg[base]; +		ARMul_Icycles (state, 1, 0L); +		shamt = state->Reg[BITS (8, 11)] & 0xff; +		switch ((int) BITS (5, 6)) { +		case LSL: +			if (shamt == 0) +				return (base); +			else if (shamt >= 32) +				return (0); +			else +				return (base << shamt); +		case LSR: +			if (shamt == 0) +				return (base); +			else if (shamt >= 32) +				return (0); +			else +				return (base >> shamt); +		case ASR: +			if (shamt == 0) +				return (base); +			else if (shamt >= 32) +				return ((ARMword) ((int) base >> 31L)); +			else +				return ((ARMword) +					(( int) base >> (int) shamt)); +		case ROR: +			shamt &= 0x1f; +			if (shamt == 0) +				return (base); +			else +				return ((base << (32 - shamt)) | +					(base >> shamt)); +		} +	} +	else { +		/* Shift amount is a constant.  */ +#ifndef MODE32 +		if (base == 15) +			base = ECC | ER15INT | R15PC | EMODE; +		else +#endif +			base = state->Reg[base]; +		shamt = BITS (7, 11); +		switch ((int) BITS (5, 6)) { +		case LSL: +			return (base << shamt); +		case LSR: +			if (shamt == 0) +				return (0); +			else +				return (base >> shamt); +		case ASR: +			if (shamt == 0) +				return ((ARMword) (( int) base >> 31L)); +			else +				return ((ARMword) +					(( int) base >> (int) shamt)); +		case ROR: +			if (shamt == 0) +				/* It's an RRX.  */ +				return ((base >> 1) | (CFLAG << 31)); +			else +				return ((base << (32 - shamt)) | +					(base >> shamt)); +		} +	} + +	return 0; +} + +/* This routine evaluates most Logical Data Processing register RHS's +   with the S bit set.  It is intended to be called from the macro +   DPSRegRHS, which filters the common case of an unshifted register +   with in line code.  */ + +static ARMword +GetDPSRegRHS (ARMul_State * state, ARMword instr) +{ +	ARMword shamt, base; + +	base = RHSReg; +	if (BIT (4)) { +		/* Shift amount in a register.  */ +		UNDEF_Shift; +		INCPC; +#ifndef MODE32 +		if (base == 15) +			base = ECC | ER15INT | R15PC | EMODE; +		else +#endif +			base = state->Reg[base]; +		ARMul_Icycles (state, 1, 0L); +		shamt = state->Reg[BITS (8, 11)] & 0xff; +		switch ((int) BITS (5, 6)) { +		case LSL: +			if (shamt == 0) +				return (base); +			else if (shamt == 32) { +				ASSIGNC (base & 1); +				return (0); +			} +			else if (shamt > 32) { +				CLEARC; +				return (0); +			} +			else { +				ASSIGNC ((base >> (32 - shamt)) & 1); +				return (base << shamt); +			} +		case LSR: +			if (shamt == 0) +				return (base); +			else if (shamt == 32) { +				ASSIGNC (base >> 31); +				return (0); +			} +			else if (shamt > 32) { +				CLEARC; +				return (0); +			} +			else { +				ASSIGNC ((base >> (shamt - 1)) & 1); +				return (base >> shamt); +			} +		case ASR: +			if (shamt == 0) +				return (base); +			else if (shamt >= 32) { +				ASSIGNC (base >> 31L); +				return ((ARMword) (( int) base >> 31L)); +			} +			else { +				ASSIGNC ((ARMword) +					 (( int) base >> +					  (int) (shamt - 1)) & 1); +				return ((ARMword) +					((int) base >> (int) shamt)); +			} +		case ROR: +			if (shamt == 0) +				return (base); +			shamt &= 0x1f; +			if (shamt == 0) { +				ASSIGNC (base >> 31); +				return (base); +			} +			else { +				ASSIGNC ((base >> (shamt - 1)) & 1); +				return ((base << (32 - shamt)) | +					(base >> shamt)); +			} +		} +	} +	else { +		/* Shift amount is a constant.  */ +#ifndef MODE32 +		if (base == 15) +			base = ECC | ER15INT | R15PC | EMODE; +		else +#endif +			base = state->Reg[base]; +		shamt = BITS (7, 11); + +		switch ((int) BITS (5, 6)) { +		case LSL: +			ASSIGNC ((base >> (32 - shamt)) & 1); +			return (base << shamt); +		case LSR: +			if (shamt == 0) { +				ASSIGNC (base >> 31); +				return (0); +			} +			else { +				ASSIGNC ((base >> (shamt - 1)) & 1); +				return (base >> shamt); +			} +		case ASR: +			if (shamt == 0) { +				ASSIGNC (base >> 31L); +				return ((ARMword) ((int) base >> 31L)); +			} +			else { +				ASSIGNC ((ARMword) +					 ((int) base >> +					  (int) (shamt - 1)) & 1); +				return ((ARMword) +					(( int) base >> (int) shamt)); +			} +		case ROR: +			if (shamt == 0) { +				/* It's an RRX.  */ +				shamt = CFLAG; +				ASSIGNC (base & 1); +				return ((base >> 1) | (shamt << 31)); +			} +			else { +				ASSIGNC ((base >> (shamt - 1)) & 1); +				return ((base << (32 - shamt)) | +					(base >> shamt)); +			} +		} +	} + +	return 0; +} + +/* This routine handles writes to register 15 when the S bit is not set.  */ + +static void +WriteR15 (ARMul_State * state, ARMword src) +{ +	/* The ARM documentation states that the two least significant bits +	   are discarded when setting PC, except in the cases handled by +	   WriteR15Branch() below.  It's probably an oversight: in THUMB +	   mode, the second least significant bit should probably not be +	   discarded.  */ +#ifdef MODET +	if (TFLAG) +		src &= 0xfffffffe; +	else +#endif +		src &= 0xfffffffc; + +#ifdef MODE32 +	state->Reg[15] = src & PCBITS; +#else +	state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE; +	ARMul_R15Altered (state); +#endif + +	FLUSHPIPE; +} + +/* This routine handles writes to register 15 when the S bit is set.  */ + +static void +WriteSR15 (ARMul_State * state, ARMword src) +{ +#ifdef MODE32 +	if (state->Bank > 0) { +		state->Cpsr = state->Spsr[state->Bank]; +		ARMul_CPSRAltered (state); +	} +#ifdef MODET +	if (TFLAG) +		src &= 0xfffffffe; +	else +#endif +		src &= 0xfffffffc; +	state->Reg[15] = src & PCBITS; +#else +#ifdef MODET +	if (TFLAG) +		/* ARMul_R15Altered would have to support it.  */ +		abort (); +	else +#endif +		src &= 0xfffffffc; + +	if (state->Bank == USERBANK) +		state->Reg[15] = +			(src & (CCBITS | R15PCBITS)) | ER15INT | EMODE; +	else +		state->Reg[15] = src; + +	ARMul_R15Altered (state); +#endif +	FLUSHPIPE; +} + +/* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM +   will switch to Thumb mode if the least significant bit is set.  */ + +static void +WriteR15Branch (ARMul_State * state, ARMword src) +{ +#ifdef MODET +	if (src & 1) { +		/* Thumb bit.  */ +		SETT; +		state->Reg[15] = src & 0xfffffffe; +	} +	else { +		CLEART; +		state->Reg[15] = src & 0xfffffffc; +	} +	state->Cpsr = ARMul_GetCPSR (state); +	FLUSHPIPE; +#else +	WriteR15 (state, src); +#endif +} + +/* This routine evaluates most Load and Store register RHS's.  It is +   intended to be called from the macro LSRegRHS, which filters the +   common case of an unshifted register with in line code.  */ + +static ARMword +GetLSRegRHS (ARMul_State * state, ARMword instr) +{ +	ARMword shamt, base; + +	base = RHSReg; +#ifndef MODE32 +	if (base == 15) +		/* Now forbidden, but ...  */ +		base = ECC | ER15INT | R15PC | EMODE; +	else +#endif +		base = state->Reg[base]; + +	shamt = BITS (7, 11); +	switch ((int) BITS (5, 6)) { +	case LSL: +		return (base << shamt); +	case LSR: +		if (shamt == 0) +			return (0); +		else +			return (base >> shamt); +	case ASR: +		if (shamt == 0) +			return ((ARMword) (( int) base >> 31L)); +		else +			return ((ARMword) (( int) base >> (int) shamt)); +	case ROR: +		if (shamt == 0) +			/* It's an RRX.  */ +			return ((base >> 1) | (CFLAG << 31)); +		else +			return ((base << (32 - shamt)) | (base >> shamt)); +	default: +		break; +	} +	return 0; +} + +/* This routine evaluates the ARM7T halfword and signed transfer RHS's.  */ + +static ARMword +GetLS7RHS (ARMul_State * state, ARMword instr) +{ +	if (BIT (22) == 0) { +		/* Register.  */ +#ifndef MODE32 +		if (RHSReg == 15) +			/* Now forbidden, but ...  */ +			return ECC | ER15INT | R15PC | EMODE; +#endif +		return state->Reg[RHSReg]; +	} + +	/* Immediate.  */ +	return BITS (0, 3) | (BITS (8, 11) << 4); +} + +/* This function does the work of loading a word for a LDR instruction.  */ +#define MEM_LOAD_LOG(description) if (skyeye_config.log.memlogon >= 1) { \ +		fprintf(skyeye_logfd, \ +			"m LOAD %s: N %llx :p %x :i %x :a %x :d %x\n", \ +			description, state->NumInstrs, state->pc, instr, \ +			address, dest); \ +	} + +#define MEM_STORE_LOG(description) if (skyeye_config.log.memlogon >= 1) { \ +		fprintf(skyeye_logfd, \ +			"m STORE %s: N %llx :p %x :i %x :a %x :d %x\n", \ +			description, state->NumInstrs, state->pc, instr, \ +			address, DEST); \ +	} + + + +static unsigned +LoadWord (ARMul_State * state, ARMword instr, ARMword address) +{ +	ARMword dest; + +	BUSUSEDINCPCS; +#ifndef MODE32 +	if (ADDREXCEPT (address)) +		INTERNALABORT (address); +#endif + +	dest = ARMul_LoadWordN (state, address); + +	if (state->Aborted) { +		TAKEABORT; +		return state->lateabtSig; +	} +	if (address & 3) +		dest = ARMul_Align (state, address, dest); +	WRITEDESTB (dest); +	ARMul_Icycles (state, 1, 0L); + +	//MEM_LOAD_LOG("WORD"); + +	return (DESTReg != LHSReg); +} + +#ifdef MODET +/* This function does the work of loading a halfword.  */ + +static unsigned +LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address, +	      int signextend) +{ +	ARMword dest; + +	BUSUSEDINCPCS; +#ifndef MODE32 +	if (ADDREXCEPT (address)) +		INTERNALABORT (address); +#endif +	dest = ARMul_LoadHalfWord (state, address); +	if (state->Aborted) { +		TAKEABORT; +		return state->lateabtSig; +	} +	UNDEF_LSRBPC; +	if (signextend) +		if (dest & 1 << (16 - 1)) +			dest = (dest & ((1 << 16) - 1)) - (1 << 16); + +	WRITEDEST (dest); +	ARMul_Icycles (state, 1, 0L); + +	//MEM_LOAD_LOG("HALFWORD"); + +	return (DESTReg != LHSReg); +} + +#endif /* MODET */ + +/* This function does the work of loading a byte for a LDRB instruction.  */ + +static unsigned +LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend) +{ +	ARMword dest; + +	BUSUSEDINCPCS; +#ifndef MODE32 +	if (ADDREXCEPT (address)) +		INTERNALABORT (address); +#endif +	dest = ARMul_LoadByte (state, address); +	if (state->Aborted) { +		TAKEABORT; +		return state->lateabtSig; +	} +	UNDEF_LSRBPC; +	if (signextend) +		if (dest & 1 << (8 - 1)) +			dest = (dest & ((1 << 8) - 1)) - (1 << 8); + +	WRITEDEST (dest); +	ARMul_Icycles (state, 1, 0L); + +	//MEM_LOAD_LOG("BYTE"); + +	return (DESTReg != LHSReg); +} + +/* This function does the work of loading two words for a LDRD instruction.  */ + +static void +Handle_Load_Double (ARMul_State * state, ARMword instr) +{ +	ARMword dest_reg; +	ARMword addr_reg; +	ARMword write_back = BIT (21); +	ARMword immediate = BIT (22); +	ARMword add_to_base = BIT (23); +	ARMword pre_indexed = BIT (24); +	ARMword offset; +	ARMword addr; +	ARMword sum; +	ARMword base; +	ARMword value1; +	ARMword value2; + +	BUSUSEDINCPCS; + +	/* If the writeback bit is set, the pre-index bit must be clear.  */ +	if (write_back && !pre_indexed) { +		ARMul_UndefInstr (state, instr); +		return; +	} + +	/* Extract the base address register.  */ +	addr_reg = LHSReg; + +	/* Extract the destination register and check it.  */ +	dest_reg = DESTReg; + +	/* Destination register must be even.  */ +	if ((dest_reg & 1) +	    /* Destination register cannot be LR.  */ +	    || (dest_reg == 14)) { +		ARMul_UndefInstr (state, instr); +		return; +	} + +	/* Compute the base address.  */ +	base = state->Reg[addr_reg]; + +	/* Compute the offset.  */ +	offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state-> +		Reg[RHSReg]; + +	/* Compute the sum of the two.  */ +	if (add_to_base) +		sum = base + offset; +	else +		sum = base - offset; + +	/* If this is a pre-indexed mode use the sum.  */ +	if (pre_indexed) +		addr = sum; +	else +		addr = base; + +	/* The address must be aligned on a 8 byte boundary.  */ +	if (addr & 0x7) { +#ifdef ABORTS +		ARMul_DATAABORT (addr); +#else +		ARMul_UndefInstr (state, instr); +#endif +		return; +	} + +	/* For pre indexed or post indexed addressing modes, +	   check that the destination registers do not overlap +	   the address registers.  */ +	if ((!pre_indexed || write_back) +	    && (addr_reg == dest_reg || addr_reg == dest_reg + 1)) { +		ARMul_UndefInstr (state, instr); +		return; +	} + +	/* Load the words.  */ +	value1 = ARMul_LoadWordN (state, addr); +	value2 = ARMul_LoadWordN (state, addr + 4); + +	/* Check for data aborts.  */ +	if (state->Aborted) { +		TAKEABORT; +		return; +	} + +	ARMul_Icycles (state, 2, 0L); + +	/* Store the values.  */ +	state->Reg[dest_reg] = value1; +	state->Reg[dest_reg + 1] = value2; + +	/* Do the post addressing and writeback.  */ +	if (!pre_indexed) +		addr = sum; + +	if (!pre_indexed || write_back) +		state->Reg[addr_reg] = addr; +} + +/* This function does the work of storing two words for a STRD instruction.  */ + +static void +Handle_Store_Double (ARMul_State * state, ARMword instr) +{ +	ARMword src_reg; +	ARMword addr_reg; +	ARMword write_back = BIT (21); +	ARMword immediate = BIT (22); +	ARMword add_to_base = BIT (23); +	ARMword pre_indexed = BIT (24); +	ARMword offset; +	ARMword addr; +	ARMword sum; +	ARMword base; + +	BUSUSEDINCPCS; + +	/* If the writeback bit is set, the pre-index bit must be clear.  */ +	if (write_back && !pre_indexed) { +		ARMul_UndefInstr (state, instr); +		return; +	} + +	/* Extract the base address register.  */ +	addr_reg = LHSReg; + +	/* Base register cannot be PC.  */ +	if (addr_reg == 15) { +		ARMul_UndefInstr (state, instr); +		return; +	} + +	/* Extract the source register.  */ +	src_reg = DESTReg; + +	/* Source register must be even.  */ +	if (src_reg & 1) { +		ARMul_UndefInstr (state, instr); +		return; +	} + +	/* Compute the base address.  */ +	base = state->Reg[addr_reg]; + +	/* Compute the offset.  */ +	offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state-> +		Reg[RHSReg]; + +	/* Compute the sum of the two.  */ +	if (add_to_base) +		sum = base + offset; +	else +		sum = base - offset; + +	/* If this is a pre-indexed mode use the sum.  */ +	if (pre_indexed) +		addr = sum; +	else +		addr = base; + +	/* The address must be aligned on a 8 byte boundary.  */ +	if (addr & 0x7) { +#ifdef ABORTS +		ARMul_DATAABORT (addr); +#else +		ARMul_UndefInstr (state, instr); +#endif +		return; +	} + +	/* For pre indexed or post indexed addressing modes, +	   check that the destination registers do not overlap +	   the address registers.  */ +	if ((!pre_indexed || write_back) +	    && (addr_reg == src_reg || addr_reg == src_reg + 1)) { +		ARMul_UndefInstr (state, instr); +		return; +	} + +	/* Load the words.  */ +	ARMul_StoreWordN (state, addr, state->Reg[src_reg]); +	ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]); + +	if (state->Aborted) { +		TAKEABORT; +		return; +	} + +	/* Do the post addressing and writeback.  */ +	if (!pre_indexed) +		addr = sum; + +	if (!pre_indexed || write_back) +		state->Reg[addr_reg] = addr; +} + +/* This function does the work of storing a word from a STR instruction.  */ + +static unsigned +StoreWord (ARMul_State * state, ARMword instr, ARMword address) +{ +	//MEM_STORE_LOG("WORD"); + +	BUSUSEDINCPCN; +#ifndef MODE32 +	if (DESTReg == 15) +		state->Reg[15] = ECC | ER15INT | R15PC | EMODE; +#endif +#ifdef MODE32 +	ARMul_StoreWordN (state, address, DEST); +#else +	if (VECTORACCESS (address) || ADDREXCEPT (address)) { +		INTERNALABORT (address); +		(void) ARMul_LoadWordN (state, address); +	} +	else +		ARMul_StoreWordN (state, address, DEST); +#endif +	if (state->Aborted) { +		TAKEABORT; +		return state->lateabtSig; +	} + +	return TRUE; +} + +#ifdef MODET +/* This function does the work of storing a byte for a STRH instruction.  */ + +static unsigned +StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address) +{ +	//MEM_STORE_LOG("HALFWORD"); + +	BUSUSEDINCPCN; + +#ifndef MODE32 +	if (DESTReg == 15) +		state->Reg[15] = ECC | ER15INT | R15PC | EMODE; +#endif + +#ifdef MODE32 +	ARMul_StoreHalfWord (state, address, DEST); +#else +	if (VECTORACCESS (address) || ADDREXCEPT (address)) { +		INTERNALABORT (address); +		(void) ARMul_LoadHalfWord (state, address); +	} +	else +		ARMul_StoreHalfWord (state, address, DEST); +#endif + +	if (state->Aborted) { +		TAKEABORT; +		return state->lateabtSig; +	} +	return TRUE; +} + +#endif /* MODET */ + +/* This function does the work of storing a byte for a STRB instruction.  */ + +static unsigned +StoreByte (ARMul_State * state, ARMword instr, ARMword address) +{ +	//MEM_STORE_LOG("BYTE"); + +	BUSUSEDINCPCN; +#ifndef MODE32 +	if (DESTReg == 15) +		state->Reg[15] = ECC | ER15INT | R15PC | EMODE; +#endif +#ifdef MODE32 +	ARMul_StoreByte (state, address, DEST); +#else +	if (VECTORACCESS (address) || ADDREXCEPT (address)) { +		INTERNALABORT (address); +		(void) ARMul_LoadByte (state, address); +	} +	else +		ARMul_StoreByte (state, address, DEST); +#endif +	if (state->Aborted) { +		TAKEABORT; +		return state->lateabtSig; +	} +	//UNDEF_LSRBPC; +	return TRUE; +} + +/* This function does the work of loading the registers listed in an LDM +   instruction, when the S bit is clear.  The code here is always increment +   after, it's up to the caller to get the input address correct and to +   handle base register modification.  */ + +static void +LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) +{ +	ARMword dest, temp; + +	//UNDEF_LSMNoRegs; +	//UNDEF_LSMPCBase; +	//UNDEF_LSMBaseInListWb; +	BUSUSEDINCPCS; +#ifndef MODE32 +	if (ADDREXCEPT (address)) +		INTERNALABORT (address); +#endif +/*chy 2004-05-23 may write twice +  if (BIT (21) && LHSReg != 15) +    LSBase = WBBase; +*/ +	/* N cycle first.  */ +	for (temp = 0; !BIT (temp); temp++); + +	dest = ARMul_LoadWordN (state, address); + +	if (!state->abortSig && !state->Aborted) +		state->Reg[temp++] = dest; +	else if (!state->Aborted) { +		XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); +		state->Aborted = ARMul_DataAbortV; +	} +/*chy 2004-05-23 chy goto end*/ +	if (state->Aborted) +		goto L_ldm_makeabort; +	/* S cycles from here on.  */ +	for (; temp < 16; temp++) +		if (BIT (temp)) { +			/* Load this register.  */ +			address += 4; +			dest = ARMul_LoadWordS (state, address); + +			if (!state->abortSig && !state->Aborted) +				state->Reg[temp] = dest; +			else if (!state->Aborted) { +				XScale_set_fsr_far (state, +						    ARMul_CP15_R5_ST_ALIGN, +						    address); +				state->Aborted = ARMul_DataAbortV; +			} +			/*chy 2004-05-23 chy goto end */ +			if (state->Aborted) +				goto L_ldm_makeabort; + +		} + +	if (BIT (15) && !state->Aborted) +		/* PC is in the reg list.  */ +		WriteR15Branch (state, PC); + +	/* To write back the final register.  */ +/*  ARMul_Icycles (state, 1, 0L);*/ +/*chy 2004-05-23, see below +  if (state->Aborted) +    { +      if (BIT (21) && LHSReg != 15) +        LSBase = WBBase; + +      TAKEABORT; +    } +*/ +/*chy 2004-05-23 should compare the Abort Models*/ +      L_ldm_makeabort: +	/* To write back the final register.  */ +	ARMul_Icycles (state, 1, 0L); + +	/* chy 2005-11-24, bug found by benjl@cse.unsw.edu.au, etc */ +	/* +	   if (state->Aborted) +	   { +	   if (BIT (21) && LHSReg != 15) +	   if (!(state->abortSig && state->Aborted && state->lateabtSig == LOW)) +	   LSBase = WBBase; +	   TAKEABORT; +	   }else if (BIT (21) && LHSReg != 15) +	   LSBase = WBBase; +	 */ +	if (state->Aborted) { +		if (BIT (21) && LHSReg != 15) { +			if (!(state->abortSig)) { +			} +		} +		TAKEABORT; +	} +	else if (BIT (21) && LHSReg != 15) { +		LSBase = WBBase; +	} +	/* chy 2005-11-24, over */ + +} + +/* This function does the work of loading the registers listed in an LDM +   instruction, when the S bit is set. The code here is always increment +   after, it's up to the caller to get the input address correct and to +   handle base register modification.  */ + +static void +LoadSMult (ARMul_State * state, +	   ARMword instr, ARMword address, ARMword WBBase) +{ +	ARMword dest, temp; + +	//UNDEF_LSMNoRegs; +	//UNDEF_LSMPCBase; +	//UNDEF_LSMBaseInListWb; + +	BUSUSEDINCPCS; + +#ifndef MODE32 +	if (ADDREXCEPT (address)) +		INTERNALABORT (address); +#endif +/* chy 2004-05-23, may write twice +  if (BIT (21) && LHSReg != 15) +    LSBase = WBBase; +*/ +	if (!BIT (15) && state->Bank != USERBANK) { +		/* Temporary reg bank switch.  */ +		(void) ARMul_SwitchMode (state, state->Mode, USER26MODE); +		UNDEF_LSMUserBankWb; +	} + +	/* N cycle first.  */ +	for (temp = 0; !BIT (temp); temp++); + +	dest = ARMul_LoadWordN (state, address); + +	if (!state->abortSig) +		state->Reg[temp++] = dest; +	else if (!state->Aborted) { +		XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); +		state->Aborted = ARMul_DataAbortV; +	} + +/*chy 2004-05-23 chy goto end*/ +	if (state->Aborted) +		goto L_ldm_s_makeabort; +	/* S cycles from here on.  */ +	for (; temp < 16; temp++) +		if (BIT (temp)) { +			/* Load this register.  */ +			address += 4; +			dest = ARMul_LoadWordS (state, address); + +			if (!state->abortSig && !state->Aborted) +				state->Reg[temp] = dest; +			else if (!state->Aborted) { +				XScale_set_fsr_far (state, +						    ARMul_CP15_R5_ST_ALIGN, +						    address); +				state->Aborted = ARMul_DataAbortV; +			} +			/*chy 2004-05-23 chy goto end */ +			if (state->Aborted) +				goto L_ldm_s_makeabort; +		} + +/*chy 2004-05-23 label of ldm_s_makeabort*/ +      L_ldm_s_makeabort: +/*chy 2004-06-06 LSBase process should be here, not in the end of this function. Because ARMul_CPSRAltered maybe change R13(SP) R14(lr). If not, simulate INSTR  ldmia sp!,[....pc]^ error.*/ +/*chy 2004-05-23 should compare the Abort Models*/ +	if (state->Aborted) { +		if (BIT (21) && LHSReg != 15) +			if (! +			    (state->abortSig && state->Aborted +			     && state->lateabtSig == LOW)) +				LSBase = WBBase; +		TAKEABORT; +	} +	else if (BIT (21) && LHSReg != 15) +		LSBase = WBBase; + +	if (BIT (15) && !state->Aborted) { +		/* PC is in the reg list.  */ +#ifdef MODE32 +	        //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode +	        if (state->Mode != USER26MODE && state->Mode != USER32MODE ){ +			state->Cpsr = GETSPSR (state->Bank); +			ARMul_CPSRAltered (state); +		} + +		WriteR15 (state, PC); +#else +	        //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode +		if (state->Mode == USER26MODE || state->Mode == USER32MODE ) { +			/* Protect bits in user mode.  */ +			ASSIGNN ((state->Reg[15] & NBIT) != 0); +			ASSIGNZ ((state->Reg[15] & ZBIT) != 0); +			ASSIGNC ((state->Reg[15] & CBIT) != 0); +			ASSIGNV ((state->Reg[15] & VBIT) != 0); +		} +		else +			ARMul_R15Altered (state); + +		FLUSHPIPE; +#endif +	} + +	        //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode +	if (!BIT (15) && state->Mode != USER26MODE +	    && state->Mode != USER32MODE ) +		/* Restore the correct bank.  */ +		(void) ARMul_SwitchMode (state, USER26MODE, state->Mode); + +	/* To write back the final register.  */ +	ARMul_Icycles (state, 1, 0L); +/* chy 2004-05-23, see below +  if (state->Aborted) +    { +      if (BIT (21) && LHSReg != 15) +        LSBase = WBBase; + +      TAKEABORT; +    } +*/ +} + +/* This function does the work of storing the registers listed in an STM +   instruction, when the S bit is clear.  The code here is always increment +   after, it's up to the caller to get the input address correct and to +   handle base register modification.  */ + +static void +StoreMult (ARMul_State * state, +	   ARMword instr, ARMword address, ARMword WBBase) +{ +	ARMword temp; + +	UNDEF_LSMNoRegs; +	UNDEF_LSMPCBase; +	UNDEF_LSMBaseInListWb; + +	if (!TFLAG) +		/* N-cycle, increment the PC and update the NextInstr state.  */ +		BUSUSEDINCPCN; + +#ifndef MODE32 +	if (VECTORACCESS (address) || ADDREXCEPT (address)) +		INTERNALABORT (address); + +	if (BIT (15)) +		PATCHR15; +#endif + +	/* N cycle first.  */ +	for (temp = 0; !BIT (temp); temp++); + +#ifdef MODE32 +	ARMul_StoreWordN (state, address, state->Reg[temp++]); +#else +	if (state->Aborted) { +		(void) ARMul_LoadWordN (state, address); + +		/* Fake the Stores as Loads.  */ +		for (; temp < 16; temp++) +			if (BIT (temp)) { +				/* Save this register.  */ +				address += 4; +				(void) ARMul_LoadWordS (state, address); +			} + +		if (BIT (21) && LHSReg != 15) +			LSBase = WBBase; +		TAKEABORT; +		return; +	} +	else +		ARMul_StoreWordN (state, address, state->Reg[temp++]); +#endif + +	if (state->abortSig && !state->Aborted) { +		XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); +		state->Aborted = ARMul_DataAbortV; +	} + +//chy 2004-05-23, needn't store other when aborted +	if (state->Aborted) +		goto L_stm_takeabort; + +	/* S cycles from here on.  */ +	for (; temp < 16; temp++) +		if (BIT (temp)) { +			/* Save this register.  */ +			address += 4; + +			ARMul_StoreWordS (state, address, state->Reg[temp]); + +			if (state->abortSig && !state->Aborted) { +				XScale_set_fsr_far (state, +						    ARMul_CP15_R5_ST_ALIGN, +						    address); +				state->Aborted = ARMul_DataAbortV; +			} +			//chy 2004-05-23, needn't store other when aborted +			if (state->Aborted) +				goto L_stm_takeabort; + +		} + +//chy 2004-05-23,should compare the Abort Models +      L_stm_takeabort: +	if (BIT (21) && LHSReg != 15) { +		if (! +		    (state->abortSig && state->Aborted +		     && state->lateabtSig == LOW)) +			LSBase = WBBase; +	} +	if (state->Aborted) +		TAKEABORT; +} + +/* This function does the work of storing the registers listed in an STM +   instruction when the S bit is set.  The code here is always increment +   after, it's up to the caller to get the input address correct and to +   handle base register modification.  */ + +static void +StoreSMult (ARMul_State * state, +	    ARMword instr, ARMword address, ARMword WBBase) +{ +	ARMword temp; + +	UNDEF_LSMNoRegs; +	UNDEF_LSMPCBase; +	UNDEF_LSMBaseInListWb; + +	BUSUSEDINCPCN; + +#ifndef MODE32 +	if (VECTORACCESS (address) || ADDREXCEPT (address)) +		INTERNALABORT (address); + +	if (BIT (15)) +		PATCHR15; +#endif + +	if (state->Bank != USERBANK) { +		/* Force User Bank.  */ +		(void) ARMul_SwitchMode (state, state->Mode, USER26MODE); +		UNDEF_LSMUserBankWb; +	} + +	for (temp = 0; !BIT (temp); temp++);	/* N cycle first.  */ + +#ifdef MODE32 +	ARMul_StoreWordN (state, address, state->Reg[temp++]); +#else +	if (state->Aborted) { +		(void) ARMul_LoadWordN (state, address); + +		for (; temp < 16; temp++) +			/* Fake the Stores as Loads.  */ +			if (BIT (temp)) { +				/* Save this register.  */ +				address += 4; + +				(void) ARMul_LoadWordS (state, address); +			} + +		if (BIT (21) && LHSReg != 15) +			LSBase = WBBase; + +		TAKEABORT; +		return; +	} +	else +		ARMul_StoreWordN (state, address, state->Reg[temp++]); +#endif + +	if (state->abortSig && !state->Aborted) { +		XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); +		state->Aborted = ARMul_DataAbortV; +	} + +//chy 2004-05-23, needn't store other when aborted +	if (state->Aborted) +		goto L_stm_s_takeabort; +	/* S cycles from here on.  */ +	for (; temp < 16; temp++) +		if (BIT (temp)) { +			/* Save this register.  */ +			address += 4; + +			ARMul_StoreWordS (state, address, state->Reg[temp]); + +			if (state->abortSig && !state->Aborted) { +				XScale_set_fsr_far (state, +						    ARMul_CP15_R5_ST_ALIGN, +						    address); +				state->Aborted = ARMul_DataAbortV; +			} +			//chy 2004-05-23, needn't store other when aborted +			if (state->Aborted) +				goto L_stm_s_takeabort; +		} + +	        //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode +	if (state->Mode != USER26MODE && state->Mode != USER32MODE ) +		/* Restore the correct bank.  */ +		(void) ARMul_SwitchMode (state, USER26MODE, state->Mode); + + +//chy 2004-05-23,should compare the Abort Models +      L_stm_s_takeabort: +	if (BIT (21) && LHSReg != 15) { +		if (! +		    (state->abortSig && state->Aborted +		     && state->lateabtSig == LOW)) +			LSBase = WBBase; +	} + +	if (state->Aborted) +		TAKEABORT; +} + +/* This function does the work of adding two 32bit values +   together, and calculating if a carry has occurred.  */ + +static ARMword +Add32 (ARMword a1, ARMword a2, int *carry) +{ +	ARMword result = (a1 + a2); +	unsigned int uresult = (unsigned int) result; +	unsigned int ua1 = (unsigned int) a1; + +	/* If (result == RdLo) and (state->Reg[nRdLo] == 0), +	   or (result > RdLo) then we have no carry.  */ +	if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1)) +		*carry = 1; +	else +		*carry = 0; + +	return result; +} + +/* This function does the work of multiplying +   two 32bit values to give a 64bit result.  */ + +static unsigned +Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc) +{ +	/* Operand register numbers.  */ +	int nRdHi, nRdLo, nRs, nRm; +	ARMword RdHi = 0, RdLo = 0, Rm; +	/* Cycle count.  */ +	int scount; + +	nRdHi = BITS (16, 19); +	nRdLo = BITS (12, 15); +	nRs = BITS (8, 11); +	nRm = BITS (0, 3); + +	/* Needed to calculate the cycle count.  */ +	Rm = state->Reg[nRm]; + +	/* Check for illegal operand combinations first.  */ +	if (nRdHi != 15 +	    && nRdLo != 15 +	    && nRs != 15 +	    //&& nRm != 15 && nRdHi != nRdLo && nRdHi != nRm && nRdLo != nRm) { +	    && nRm != 15 && nRdHi != nRdLo ) { +		/* Intermediate results.  */ +		ARMword lo, mid1, mid2, hi; +		int carry; +		ARMword Rs = state->Reg[nRs]; +		int sign = 0; + +		if (msigned) { +			/* Compute sign of result and adjust operands if necessary.  */ +			sign = (Rm ^ Rs) & 0x80000000; + +			if (((signed int) Rm) < 0) +				Rm = -Rm; + +			if (((signed int) Rs) < 0) +				Rs = -Rs; +		} + +		/* We can split the 32x32 into four 16x16 operations. This +		   ensures that we do not lose precision on 32bit only hosts.  */ +		lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF)); +		mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); +		mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF)); +		hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); + +		/* We now need to add all of these results together, taking +		   care to propogate the carries from the additions.  */ +		RdLo = Add32 (lo, (mid1 << 16), &carry); +		RdHi = carry; +		RdLo = Add32 (RdLo, (mid2 << 16), &carry); +		RdHi += (carry + ((mid1 >> 16) & 0xFFFF) + +			 ((mid2 >> 16) & 0xFFFF) + hi); + +		if (sign) { +			/* Negate result if necessary.  */ +			RdLo = ~RdLo; +			RdHi = ~RdHi; +			if (RdLo == 0xFFFFFFFF) { +				RdLo = 0; +				RdHi += 1; +			} +			else +				RdLo += 1; +		} + +		state->Reg[nRdLo] = RdLo; +		state->Reg[nRdHi] = RdHi; +	} +	else{ +		fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS, instr=0x%x\n", instr); +	} +	if (scc) +		/* Ensure that both RdHi and RdLo are used to compute Z, +		   but don't let RdLo's sign bit make it to N.  */ +		ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); + +	/* The cycle count depends on whether the instruction is a signed or +	   unsigned multiply, and what bits are clear in the multiplier.  */ +	if (msigned && (Rm & ((unsigned) 1 << 31))) +		/* Invert the bits to make the check against zero.  */ +		Rm = ~Rm; + +	if ((Rm & 0xFFFFFF00) == 0) +		scount = 1; +	else if ((Rm & 0xFFFF0000) == 0) +		scount = 2; +	else if ((Rm & 0xFF000000) == 0) +		scount = 3; +	else +		scount = 4; + +	return 2 + scount; +} + +/* This function does the work of multiplying two 32bit +   values and adding a 64bit value to give a 64bit result.  */ + +static unsigned +MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc) +{ +	unsigned scount; +	ARMword RdLo, RdHi; +	int nRdHi, nRdLo; +	int carry = 0; + +	nRdHi = BITS (16, 19); +	nRdLo = BITS (12, 15); + +	RdHi = state->Reg[nRdHi]; +	RdLo = state->Reg[nRdLo]; + +	scount = Multiply64 (state, instr, msigned, LDEFAULT); + +	RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry); +	RdHi = (RdHi + state->Reg[nRdHi]) + carry; + +	state->Reg[nRdLo] = RdLo; +	state->Reg[nRdHi] = RdHi; + +	if (scc) +		/* Ensure that both RdHi and RdLo are used to compute Z, +		   but don't let RdLo's sign bit make it to N.  */ +		ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); + +	/* Extra cycle for addition.  */ +	return scount + 1; +} + +/* Attempt to emulate an ARMv6 instruction. +   Returns non-zero upon success.  */ + +static int +handle_v6_insn (ARMul_State * state, ARMword instr) +{ +  switch (BITS (20, 27)) +    { +#if 0 +    case 0x03: printf ("Unhandled v6 insn: ldr\n"); break; +    case 0x04: printf ("Unhandled v6 insn: umaal\n"); break; +    case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break; +    case 0x16: printf ("Unhandled v6 insn: smi\n"); break; +    case 0x18: printf ("Unhandled v6 insn: strex\n"); break; +    case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break; +    case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break; +    case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break; +    case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break; +    case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break; +    case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break; +    case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break; +    case 0x30: printf ("Unhandled v6 insn: movw\n"); break; +    case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break; +    case 0x34: printf ("Unhandled v6 insn: movt\n"); break; +    case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break; +    case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break; +    case 0x62: printf ("Unhandled v6 insn: qadd/qsub\n"); break; +    case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break; +    case 0x65: printf ("Unhandled v6 insn: uadd/usub\n"); break; +    case 0x66: printf ("Unhandled v6 insn: uqadd/uqsub\n"); break; +    case 0x67: printf ("Unhandled v6 insn: uhadd/uhsub\n"); break; +    case 0x68: printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); break; +#endif +    case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break; +    case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break; +    case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break; +    case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break; +    case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break; +#if 0 +    case 0x7a: printf ("Unhandled v6 insn: usbfx\n"); break; +    case 0x7c: printf ("Unhandled v6 insn: bfc/bfi\n"); break; +#endif + + +/* add new instr for arm v6. */ +    ARMword lhs, temp; +    case 0x18:	/* ORR reg */ +      { +	/* dyf add armv6 instr strex  2010.9.17 */ +	 if (BITS (4, 7) == 0x9) { +		lhs = LHS; +		ARMul_StoreWordS(state, lhs, RHS); +		//StoreWord(state, lhs, RHS) +		if (state->Aborted) { +			TAKEABORT; +		} + +		return 1; +	 } +	 break; +      } + +    case 0x19:	/* orrs reg */ +      { +	/* dyf add armv6 instr ldrex  */ +	if (BITS (4, 7) == 0x9) { +		lhs = LHS; +		LoadWord (state, instr, lhs); +		return 1; +	} +	break; +      } + +    case 0x1c:	/* BIC reg */ +      { +	/* dyf add for STREXB */ +	if (BITS (4, 7) == 0x9) { +		lhs = LHS; +		ARMul_StoreByte (state, lhs, RHS); +		BUSUSEDINCPCN; +		if (state->Aborted) { +			TAKEABORT; +		} + +		//printf("In %s, strexb not implemented\n", __FUNCTION__); +		UNDEF_LSRBPC; +		/* WRITESDEST (dest); */ +		return 1; +	} +	break; +      } + +    case 0x1d:	/* BICS reg */ +      { +	if ((BITS (4, 7)) == 0x9) { +		/* ldrexb */ +		temp = LHS; +		LoadByte (state, instr, temp, LUNSIGNED); +        //state->Reg[BITS(12, 15)] = ARMul_LoadByte(state, state->Reg[BITS(16, 19)]); +        //printf("ldrexb\n"); +        //printf("instr is %x rm is %d\n", instr, BITS(16, 19)); +        //exit(-1); +		 +		//printf("In %s, ldrexb not implemented\n", __FUNCTION__); +		return 1; +    } +	break; +      } +/* add end */ + +    case 0x6a: +      { +	ARMword Rm; +	int ror = -1; +	   +	switch (BITS (4, 11)) +	  { +	  case 0x07: ror = 0; break; +	  case 0x47: ror = 8; break; +	  case 0x87: ror = 16; break; +	  case 0xc7: ror = 24; break; + +	  case 0x01: +	  case 0xf3: +	    printf ("Unhandled v6 insn: ssat\n"); +	    return 0; +	  default: +	    break; +	  } +	 +	if (ror == -1) +	  { +	    if (BITS (4, 6) == 0x7) +	      { +		printf ("Unhandled v6 insn: ssat\n"); +		return 0; +	      } +	    break; +	  } + +	Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF); +	if (Rm & 0x80) +	  Rm |= 0xffffff00; + +	if (BITS (16, 19) == 0xf) +	   /* SXTB */ +	  state->Reg[BITS (12, 15)] = Rm; +	else +	  /* SXTAB */ +	  state->Reg[BITS (12, 15)] += Rm; +      } +      return 1; + +    case 0x6b: +      { +	ARMword Rm; +	int ror = -1; +	   +	switch (BITS (4, 11)) +	  { +	  case 0x07: ror = 0; break; +	  case 0x47: ror = 8; break; +	  case 0x87: ror = 16; break; +	  case 0xc7: ror = 24; break; + +	  case 0xf3: +	    DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24); +	    return 1; +	  case 0xfb: +	    DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8); +	    return 1; +	  default: +	    break; +	  } +	 +	if (ror == -1) +	  break; + +	Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF); +	if (Rm & 0x8000) +	  Rm |= 0xffff0000; + +	if (BITS (16, 19) == 0xf) +	  /* SXTH */ +	  state->Reg[BITS (12, 15)] = Rm; +	else +	  /* SXTAH */ +	  state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm; +      } +      return 1; + +    case 0x6e: +      { +	ARMword Rm; +	int ror = -1; +	   +	switch (BITS (4, 11)) +	  { +	  case 0x07: ror = 0; break; +	  case 0x47: ror = 8; break; +	  case 0x87: ror = 16; break; +	  case 0xc7: ror = 24; break; + +	  case 0x01: +	  case 0xf3: +	    printf ("Unhandled v6 insn: usat\n"); +	    return 0; +	  default: +	    break; +	  } +	 +	if (ror == -1) +	  { +	    if (BITS (4, 6) == 0x7) +	      { +		printf ("Unhandled v6 insn: usat\n"); +		return 0; +	      } +	    break; +	  } + +	Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF); + +	if (BITS (16, 19) == 0xf) +	   /* UXTB */ +	  state->Reg[BITS (12, 15)] = Rm; +	else +	  /* UXTAB */ +	  state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm; +      } +      return 1; + +    case 0x6f: +      { +	ARMword Rm; +	int ror = -1; +	   +	switch (BITS (4, 11)) +	  { +	  case 0x07: ror = 0; break; +	  case 0x47: ror = 8; break; +	  case 0x87: ror = 16; break; +	  case 0xc7: ror = 24; break; + +	  case 0xfb: +	    printf ("Unhandled v6 insn: revsh\n"); +	    return 0; +	  default: +	    break; +	  } +	 +	if (ror == -1) +	  break; + +	Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF); + +	  /* UXT */ +	/* state->Reg[BITS (12, 15)] = Rm; */ +          /* dyf add */ +	if (BITS (16, 19) == 0xf) { +	  state->Reg[BITS (12, 15)] = (Rm >> (8 * BITS(10, 11))) & 0x0000FFFF; +	} else { +	    /* UXTAH */ +	    /* state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm; */ +//            printf("rd is %x rn is %x rm is %x rotate is %x\n", state->Reg[BITS (12, 15)], state->Reg[BITS (16, 19)] +//                   , Rm, BITS(10, 11)); +//            printf("icounter is %lld\n", state->NumInstrs); +	    state->Reg[BITS (12, 15)] = (state->Reg[BITS (16, 19)] >> (8 * (BITS(10, 11)))) + Rm; +//        printf("rd is %x\n", state->Reg[BITS (12, 15)]); +//        exit(-1); +	} +      } +      return 1; + +#if 0 +    case 0x84: printf ("Unhandled v6 insn: srs\n"); break; +#endif +    default: +      break; +    } +  printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr); +  return 0; +} diff --git a/src/core/src/arm/armemu.h b/src/core/src/arm/armemu.h new file mode 100644 index 000000000..ae5c35aee --- /dev/null +++ b/src/core/src/arm/armemu.h @@ -0,0 +1,657 @@ +/*  armemu.h -- ARMulator emulation macros:  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. */ +#ifndef __ARMEMU_H__ +#define __ARMEMU_H__ + +#include "common.h" +#include "armdefs.h" +//#include "skyeye.h" + +extern ARMword isize; + +/* Condition code values.  */ +#define EQ 0 +#define NE 1 +#define CS 2 +#define CC 3 +#define MI 4 +#define PL 5 +#define VS 6 +#define VC 7 +#define HI 8 +#define LS 9 +#define GE 10 +#define LT 11 +#define GT 12 +#define LE 13 +#define AL 14 +#define NV 15 + +/* Shift Opcodes.  */ +#define LSL 0 +#define LSR 1 +#define ASR 2 +#define ROR 3 + +/* Macros to twiddle the status flags and mode.  */ +#define NBIT ((unsigned)1L << 31) +#define ZBIT (1L << 30) +#define CBIT (1L << 29) +#define VBIT (1L << 28) +#define SBIT (1L << 27) +#define IBIT (1L << 7) +#define FBIT (1L << 6) +#define IFBITS (3L << 6) +#define R15IBIT (1L << 27) +#define R15FBIT (1L << 26) +#define R15IFBITS (3L << 26) + +#define POS(i) ( (~(i)) >> 31 ) +#define NEG(i) ( (i) >> 31 ) + +#ifdef MODET			/* Thumb support.  */ +/* ??? This bit is actually in the low order bit of the PC in the hardware. +   It isn't clear if the simulator needs to model that or not.  */ +#define TBIT (1L << 5) +#define TFLAG state->TFlag +#define SETT state->TFlag = 1 +#define CLEART state->TFlag = 0 +#define ASSIGNT(res) state->TFlag = res +#define INSN_SIZE (TFLAG ? 2 : 4) +#else +#define INSN_SIZE 4 +#define TFLAG 0 +#endif + +/*add armv6 CPSR  feature*/ +#define EFLAG state->EFlag +#define SETE state->EFlag = 1 +#define CLEARE state->EFlag = 0 +#define ASSIGNE(res) state->NFlag = res + +#define AFLAG state->AFlag +#define SETA  state->AFlag = 1 +#define CLEARA state->AFlag = 0 +#define ASSIGNA(res) state->NFlag = res + +#define QFLAG state->QFlag +#define SETQ state->QFlag = 1 +#define CLEARQ state->AFlag = 0 +#define ASSIGNQ(res) state->QFlag = res + +/* add end */ + +#define NFLAG state->NFlag +#define SETN state->NFlag = 1 +#define CLEARN state->NFlag = 0 +#define ASSIGNN(res) state->NFlag = res + +#define ZFLAG state->ZFlag +#define SETZ state->ZFlag = 1 +#define CLEARZ state->ZFlag = 0 +#define ASSIGNZ(res) state->ZFlag = res + +#define CFLAG state->CFlag +#define SETC state->CFlag = 1 +#define CLEARC state->CFlag = 0 +#define ASSIGNC(res) state->CFlag = res + +#define VFLAG state->VFlag +#define SETV state->VFlag = 1 +#define CLEARV state->VFlag = 0 +#define ASSIGNV(res) state->VFlag = res + +#define SFLAG state->SFlag +#define SETS state->SFlag = 1 +#define CLEARS state->SFlag = 0 +#define ASSIGNS(res) state->SFlag = res + +#define IFLAG (state->IFFlags >> 1) +#define FFLAG (state->IFFlags & 1) +#define IFFLAGS state->IFFlags +#define ASSIGNINT(res) state->IFFlags = (((res) >> 6) & 3) +#define ASSIGNR15INT(res) state->IFFlags = (((res) >> 26) & 3) ; + +#define PSR_FBITS (0xff000000L) +#define PSR_SBITS (0x00ff0000L) +#define PSR_XBITS (0x0000ff00L) +#define PSR_CBITS (0x000000ffL) + +#if defined MODE32 || defined MODET +#define CCBITS (0xf8000000L) +#else +#define CCBITS (0xf0000000L) +#endif + +#define INTBITS (0xc0L) + +#if defined MODET && defined MODE32 +#define PCBITS (0xffffffffL) +#else +#define PCBITS (0xfffffffcL) +#endif + +#define MODEBITS (0x1fL) +#define R15INTBITS (3L << 26) + +#if defined MODET && defined MODE32 +#define R15PCBITS (0x03ffffffL) +#else +#define R15PCBITS (0x03fffffcL) +#endif + +#define R15PCMODEBITS (0x03ffffffL) +#define R15MODEBITS (0x3L) + +#ifdef MODE32 +#define PCMASK PCBITS +#define PCWRAP(pc) (pc) +#else +#define PCMASK R15PCBITS +#define PCWRAP(pc) ((pc) & R15PCBITS) +#endif + +#define PC (state->Reg[15] & PCMASK) +#define R15CCINTMODE (state->Reg[15] & (CCBITS | R15INTBITS | R15MODEBITS)) +#define R15INT (state->Reg[15] & R15INTBITS) +#define R15INTPC (state->Reg[15] & (R15INTBITS | R15PCBITS)) +#define R15INTPCMODE (state->Reg[15] & (R15INTBITS | R15PCBITS | R15MODEBITS)) +#define R15INTMODE (state->Reg[15] & (R15INTBITS | R15MODEBITS)) +#define R15PC (state->Reg[15] & R15PCBITS) +#define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS)) +#define R15MODE (state->Reg[15] & R15MODEBITS) + +#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (SFLAG << 27)) +#define EINT (IFFLAGS << 6) +#define ER15INT (IFFLAGS << 26) +#define EMODE (state->Mode) + +#ifdef MODET +#define CPSR (ECC | EINT | EMODE | (TFLAG << 5)) +#else +#define CPSR (ECC | EINT | EMODE) +#endif + +#ifdef MODE32 +#define PATCHR15 +#else +#define PATCHR15 state->Reg[15] = ECC | ER15INT | EMODE | R15PC +#endif + +#define GETSPSR(bank) (ARMul_GetSPSR (state, EMODE)) +#define SETPSR_F(d,s) d = ((d) & ~PSR_FBITS) | ((s) & PSR_FBITS) +#define SETPSR_S(d,s) d = ((d) & ~PSR_SBITS) | ((s) & PSR_SBITS) +#define SETPSR_X(d,s) d = ((d) & ~PSR_XBITS) | ((s) & PSR_XBITS) +#define SETPSR_C(d,s) d = ((d) & ~PSR_CBITS) | ((s) & PSR_CBITS) + +#define SETR15PSR(s) 								\ +  do										\ +    {										\ +      if (state->Mode == USER26MODE)						\ +        {									\ +          state->Reg[15] = ((s) & CCBITS) | R15PC | ER15INT | EMODE;		\ +          ASSIGNN ((state->Reg[15] & NBIT) != 0);				\ +          ASSIGNZ ((state->Reg[15] & ZBIT) != 0);				\ +          ASSIGNC ((state->Reg[15] & CBIT) != 0);				\ +          ASSIGNV ((state->Reg[15] & VBIT) != 0);				\ +        }									\ +      else									\ +        {									\ +          state->Reg[15] = R15PC | ((s) & (CCBITS | R15INTBITS | R15MODEBITS));	\ +          ARMul_R15Altered (state);						\ +       }									\ +    }										\ +  while (0) + +#define SETABORT(i, m, d)						\ +  do									\ +    { 									\ +      int SETABORT_mode = (m);						\ +									\ +      ARMul_SetSPSR (state, SETABORT_mode, ARMul_GetCPSR (state));	\ +      ARMul_SetCPSR (state, ((ARMul_GetCPSR (state) & ~(EMODE | TBIT))	\ +			     | (i) | SETABORT_mode));			\ +      state->Reg[14] = temp - (d);					\ +    }									\ +  while (0) + +#ifndef MODE32 +#define VECTORS 0x20 +#define LEGALADDR 0x03ffffff +#define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig) +#define ADDREXCEPT(address)   (address > LEGALADDR && !state->data32Sig) +#endif + +#define INTERNALABORT(address)			\ +  do						\ +    {						\ +      if (address < VECTORS)			\ +	state->Aborted = ARMul_DataAbortV;	\ +      else					\ +	state->Aborted = ARMul_AddrExceptnV;	\ +    }						\ +  while (0) + +#ifdef MODE32 +#define TAKEABORT ARMul_Abort (state, ARMul_DataAbortV) +#else +#define TAKEABORT 					\ +  do							\ +    {							\ +      if (state->Aborted == ARMul_AddrExceptnV) 	\ +	ARMul_Abort (state, ARMul_AddrExceptnV); 	\ +      else 						\ +	ARMul_Abort (state, ARMul_DataAbortV);		\ +    }							\ +  while (0) +#endif + +#define CPTAKEABORT					\ +  do							\ +    {							\ +      if (!state->Aborted)				\ +	ARMul_Abort (state, ARMul_UndefinedInstrV); 	\ +      else if (state->Aborted == ARMul_AddrExceptnV) 	\ +	ARMul_Abort (state, ARMul_AddrExceptnV); 	\ +      else 						\ +	ARMul_Abort (state, ARMul_DataAbortV);		\ +    }							\ +  while (0); + + +/* Different ways to start the next instruction.  */ +#define SEQ           0 +#define NONSEQ        1 +#define PCINCEDSEQ    2 +#define PCINCEDNONSEQ 3 +#define PRIMEPIPE     4 +#define RESUME        8 + +/************************************/ +/* shenoubang 2012-3-11 */ +/* for armv7 DBG DMB DSB instr*/ +/************************************/ +#define MBReqTypes_Writes	0 +#define MBReqTypes_All		1 + +#define NORMALCYCLE state->NextInstr = 0 +#define BUSUSEDN    state->NextInstr |= 1	/* The next fetch will be an N cycle.  */ +#define BUSUSEDINCPCS						\ +  do								\ +    {								\ +      if (! state->is_v4)					\ +        {							\ +	  /* A standard PC inc and an S cycle.  */		\ +	  state->Reg[15] += isize;				\ +	  state->NextInstr = (state->NextInstr & 0xff) | 2;	\ +	}							\ +    }								\ +  while (0) + +#define BUSUSEDINCPCN					\ +  do							\ +    {							\ +      if (state->is_v4)					\ +	BUSUSEDN;					\ +      else						\ +	{						\ +	  /* A standard PC inc and an N cycle.  */	\ +	  state->Reg[15] += isize;			\ +	  state->NextInstr |= 3;			\ +	}						\ +    }							\ +  while (0) + +#define INCPC 			\ +  do				\ +    {				\ +      /* A standard PC inc.  */	\ +      state->Reg[15] += isize;	\ +      state->NextInstr |= 2;	\ +    }				\ +  while (0) + +#define FLUSHPIPE state->NextInstr |= PRIMEPIPE + +/* Cycle based emulation.  */ + +#define OUTPUTCP(i,a,b) +#define NCYCLE +#define SCYCLE +#define ICYCLE +#define CCYCLE +#define NEXTCYCLE(c) + +/* Macros to extract parts of instructions.  */ +#define DESTReg (BITS (12, 15)) +#define LHSReg  (BITS (16, 19)) +#define RHSReg  (BITS ( 0,  3)) + +#define DEST (state->Reg[DESTReg]) + +#ifdef MODE32 +#ifdef MODET +#define LHS ((LHSReg == 15) ? (state->Reg[15] & 0xFFFFFFFC) : (state->Reg[LHSReg])) +#define RHS ((RHSReg == 15) ? (state->Reg[15] & 0xFFFFFFFC) : (state->Reg[RHSReg])) +#else +#define LHS (state->Reg[LHSReg]) +#define RHS (state->Reg[RHSReg]) +#endif +#else +#define LHS ((LHSReg == 15) ? R15PC : (state->Reg[LHSReg])) +#define RHS ((RHSReg == 15) ? R15PC : (state->Reg[RHSReg])) +#endif + +#define MULDESTReg (BITS (16, 19)) +#define MULLHSReg  (BITS ( 0,  3)) +#define MULRHSReg  (BITS ( 8, 11)) +#define MULACCReg  (BITS (12, 15)) + +#define DPImmRHS (ARMul_ImmedTable[BITS(0, 11)]) +#define DPSImmRHS temp = BITS(0,11) ; \ +                  rhs = ARMul_ImmedTable[temp] ; \ +                  if (temp > 255) /* There was a shift.  */ \ +                     ASSIGNC (rhs >> 31) ; + +#ifdef MODE32 +#define DPRegRHS  ((BITS (4,11) == 0) ? state->Reg[RHSReg] \ +                                      : GetDPRegRHS (state, instr)) +#define DPSRegRHS ((BITS (4,11) == 0) ? state->Reg[RHSReg] \ +                                      : GetDPSRegRHS (state, instr)) +#else +#define DPRegRHS  ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \ +                                       : GetDPRegRHS (state, instr)) +#define DPSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \ +                                       : GetDPSRegRHS (state, instr)) +#endif + +#define LSBase state->Reg[LHSReg] +#define LSImmRHS (BITS(0,11)) + +#ifdef MODE32 +#define LSRegRHS ((BITS (4, 11) == 0) ? state->Reg[RHSReg] \ +                                      : GetLSRegRHS (state, instr)) +#else +#define LSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \ +                                      : GetLSRegRHS (state, instr)) +#endif + +#define LSMNumRegs ((ARMword) ARMul_BitList[BITS (0, 7)] + \ +                    (ARMword) ARMul_BitList[BITS (8, 15)] ) +#define LSMBaseFirst ((LHSReg == 0 && BIT (0)) || \ +                      (BIT (LHSReg) && BITS (0, LHSReg - 1) == 0)) + +#define SWAPSRC (state->Reg[RHSReg]) + +#define LSCOff (BITS (0, 7) << 2) +#define CPNum   BITS (8, 11) + +/* Determine if access to coprocessor CP is permitted. +   The XScale has a register in CP15 which controls access to CP0 - CP13.  */ +//chy 2003-09-03, new CP_ACCESS_ALLOWED +/* +#define CP_ACCESS_ALLOWED(STATE, CP)			\ +    (   ((CP) >= 14)					\ +     || (! (STATE)->is_XScale)				\ +     || (read_cp15_reg (15, 0, 1) & (1 << (CP)))) +*/ +#define CP_ACCESS_ALLOWED(STATE, CP)			\ +    (   ((CP) >= 14)					\ +     || (! (STATE)->is_XScale)				\ +     || (xscale_cp15_cp_access_allowed(STATE,15,CP))) + +/* Macro to rotate n right by b bits.  */ +#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b)))) + +/* Macros to store results of instructions.  */ +#define WRITEDEST(d)				\ +  do						\ +    {						\ +      if (DESTReg == 15) 			\ +	WriteR15 (state, d); 			\ +      else 					\ +	DEST = d;				\ +    }						\ +  while (0) + +#define WRITESDEST(d)				\ +  do						\ +    {						\ +      if (DESTReg == 15)			\ +	WriteSR15 (state, d);			\ +      else					\ +	{					\ +	  DEST = d;				\ +	  ARMul_NegZero (state, d);		\ +	}					\ +    }						\ +  while (0) + +#define WRITEDESTB(d)				\ +  do						\ +    {						\ +      if (DESTReg == 15){			\ +	WriteR15Branch (state, d);		\ +      }						\ +      else{					\ +	DEST = d;				\ +      }						\ +    }						\ +  while (0) + +#define BYTETOBUS(data) ((data & 0xff) | \ +                        ((data & 0xff) << 8) | \ +                        ((data & 0xff) << 16) | \ +                        ((data & 0xff) << 24)) + +#define BUSTOBYTE(address, data)				\ +  do								\ +    {								\ +      if (state->bigendSig) 					\ +	temp = (data >> (((address ^ 3) & 3) << 3)) & 0xff;	\ +      else							\ +	temp = (data >> ((address & 3) << 3)) & 0xff;		\ +    }								\ +  while (0) + +#define LOADMULT(instr,   address, wb)  LoadMult   (state, instr, address, wb) +#define LOADSMULT(instr,  address, wb)  LoadSMult  (state, instr, address, wb) +#define STOREMULT(instr,  address, wb)  StoreMult  (state, instr, address, wb) +#define STORESMULT(instr, address, wb)  StoreSMult (state, instr, address, wb) + +#define POSBRANCH ((instr & 0x7fffff) << 2) +#define NEGBRANCH ((0xff000000 |(instr & 0xffffff)) << 2) + + +/* Values for Emulate.  */ +#define STOP            0	/* stop */ +#define CHANGEMODE      1	/* change mode */ +#define ONCE            2	/* execute just one interation */ +#define RUN             3	/* continuous execution */ + +/* Stuff that is shared across modes.  */ +extern unsigned ARMul_MultTable[];	/* Number of I cycles for a mult.  */ +extern ARMword ARMul_ImmedTable[];	/* Immediate DP LHS values.  */ +extern char ARMul_BitList[];	/* Number of bits in a byte table.  */ + +#define EVENTLISTSIZE 1024L + +/* Thumb support.  */ +typedef enum +{ +	t_undefined,		/* Undefined Thumb instruction.  */ +	t_decoded,		/* Instruction decoded to ARM equivalent.  */ +	t_branch		/* Thumb branch (already processed).  */ +} +tdstate; + +/********************************************************************************* + * Check all the possible undef or unpredict behavior, Some of them probably is + * out-of-updated with the newer ISA. + * -- Michael.Kang + ********************************************************************************/ +#define UNDEF_WARNING ERROR_LOG(ARM11, "undefined or unpredicted behavior for arm instruction.\n"); + +/* Macros to scrutinize instructions.  */ +#define UNDEF_Test UNDEF_WARNING +//#define UNDEF_Test + +//#define UNDEF_Shift UNDEF_WARNING +#define UNDEF_Shift + +//#define UNDEF_MSRPC UNDEF_WARNING +#define UNDEF_MSRPC + +//#define UNDEF_MRSPC UNDEF_WARNING +#define UNDEF_MRSPC + +#define UNDEF_MULPCDest UNDEF_WARNING +//#define UNDEF_MULPCDest + +#define UNDEF_MULDestEQOp1 UNDEF_WARNING +//#define UNDEF_MULDestEQOp1 + +//#define UNDEF_LSRBPC UNDEF_WARNING +#define UNDEF_LSRBPC + +//#define UNDEF_LSRBaseEQOffWb UNDEF_WARNING +#define UNDEF_LSRBaseEQOffWb + +//#define UNDEF_LSRBaseEQDestWb UNDEF_WARNING +#define UNDEF_LSRBaseEQDestWb + +//#define UNDEF_LSRPCBaseWb UNDEF_WARNING +#define UNDEF_LSRPCBaseWb + +//#define UNDEF_LSRPCOffWb UNDEF_WARNING +#define UNDEF_LSRPCOffWb + +//#define UNDEF_LSMNoRegs UNDEF_WARNING +#define UNDEF_LSMNoRegs + +//#define UNDEF_LSMPCBase UNDEF_WARNING +#define UNDEF_LSMPCBase + +//#define UNDEF_LSMUserBankWb UNDEF_WARNING +#define UNDEF_LSMUserBankWb + +//#define UNDEF_LSMBaseInListWb UNDEF_WARNING +#define UNDEF_LSMBaseInListWb + +#define UNDEF_SWPPC UNDEF_WARNING +//#define UNDEF_SWPPC + +#define UNDEF_CoProHS UNDEF_WARNING +//#define UNDEF_CoProHS + +#define UNDEF_MCRPC UNDEF_WARNING +//#define UNDEF_MCRPC + +//#define UNDEF_LSCPCBaseWb UNDEF_WARNING +#define UNDEF_LSCPCBaseWb + +#define UNDEF_UndefNotBounced UNDEF_WARNING +//#define UNDEF_UndefNotBounced + +#define UNDEF_ShortInt UNDEF_WARNING +//#define UNDEF_ShortInt + +#define UNDEF_IllegalMode UNDEF_WARNING +//#define UNDEF_IllegalMode + +#define UNDEF_Prog32SigChange UNDEF_WARNING +//#define UNDEF_Prog32SigChange + +#define UNDEF_Data32SigChange UNDEF_WARNING +//#define UNDEF_Data32SigChange + +/* Prototypes for exported functions.  */ +extern unsigned ARMul_NthReg (ARMword, unsigned); +extern int AddOverflow (ARMword, ARMword, ARMword); +extern int SubOverflow (ARMword, ARMword, ARMword); +/* Prototypes for exported functions.  */ +#ifdef __cplusplus + extern "C" { +#endif +extern ARMword ARMul_Emulate26 (ARMul_State *); +extern ARMword ARMul_Emulate32 (ARMul_State *); +#ifdef __cplusplus + } +#endif +extern unsigned IntPending (ARMul_State *); +extern void ARMul_CPSRAltered (ARMul_State *); +extern void ARMul_R15Altered (ARMul_State *); +extern ARMword ARMul_GetPC (ARMul_State *); +extern ARMword ARMul_GetNextPC (ARMul_State *); +extern ARMword ARMul_GetR15 (ARMul_State *); +extern ARMword ARMul_GetCPSR (ARMul_State *); +extern void ARMul_EnvokeEvent (ARMul_State *); +extern unsigned int ARMul_Time (ARMul_State *); +extern void ARMul_NegZero (ARMul_State *, ARMword); +extern void ARMul_SetPC (ARMul_State *, ARMword); +extern void ARMul_SetR15 (ARMul_State *, ARMword); +extern void ARMul_SetCPSR (ARMul_State *, ARMword); +extern ARMword ARMul_GetSPSR (ARMul_State *, ARMword); +extern void ARMul_Abort26 (ARMul_State *, ARMword); +extern void ARMul_Abort32 (ARMul_State *, ARMword); +extern ARMword ARMul_MRC (ARMul_State *, ARMword); +extern void ARMul_MRRC (ARMul_State *, ARMword, ARMword *, ARMword *); +extern void ARMul_CDP (ARMul_State *, ARMword); +extern void ARMul_LDC (ARMul_State *, ARMword, ARMword); +extern void ARMul_STC (ARMul_State *, ARMword, ARMword); +extern void ARMul_MCR (ARMul_State *, ARMword, ARMword); +extern void ARMul_MCRR (ARMul_State *, ARMword, ARMword, ARMword); +extern void ARMul_SetSPSR (ARMul_State *, ARMword, ARMword); +extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword); +extern ARMword ARMul_Align (ARMul_State *, ARMword, ARMword); +extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword); +extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword); +extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword); +extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword); +extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword); +extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword); +extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *); +extern ARMword ARMul_GetReg (ARMul_State *, unsigned, unsigned); +extern void ARMul_SetReg (ARMul_State *, unsigned, unsigned, ARMword); +extern void ARMul_ScheduleEvent (ARMul_State *, unsigned int, +				 unsigned (*)(ARMul_State *)); +/* Coprocessor support functions.  */ +extern unsigned ARMul_CoProInit (ARMul_State *); +extern void ARMul_CoProExit (ARMul_State *); +extern void ARMul_CoProAttach (ARMul_State *, unsigned, ARMul_CPInits *, +			       ARMul_CPExits *, ARMul_LDCs *, ARMul_STCs *, +			       ARMul_MRCs *, ARMul_MCRs *, ARMul_MRRCs *, ARMul_MCRRs *,  +			       ARMul_CDPs *, ARMul_CPReads *, ARMul_CPWrites *); +extern void ARMul_CoProDetach (ARMul_State *, unsigned); +extern ARMword read_cp15_reg (unsigned, unsigned, unsigned); + +extern unsigned DSPLDC4 (ARMul_State *, unsigned, ARMword, ARMword); +extern unsigned DSPMCR4 (ARMul_State *, unsigned, ARMword, ARMword); +extern unsigned DSPMRC4 (ARMul_State *, unsigned, ARMword, ARMword *); +extern unsigned DSPSTC4 (ARMul_State *, unsigned, ARMword, ARMword *); +extern unsigned DSPCDP4 (ARMul_State *, unsigned, ARMword); +extern unsigned DSPMCR5 (ARMul_State *, unsigned, ARMword, ARMword); +extern unsigned DSPMRC5 (ARMul_State *, unsigned, ARMword, ARMword *); +extern unsigned DSPLDC5 (ARMul_State *, unsigned, ARMword, ARMword); +extern unsigned DSPSTC5 (ARMul_State *, unsigned, ARMword, ARMword *); +extern unsigned DSPCDP5 (ARMul_State *, unsigned, ARMword); +extern unsigned DSPMCR6 (ARMul_State *, unsigned, ARMword, ARMword); +extern unsigned DSPMRC6 (ARMul_State *, unsigned, ARMword, ARMword *); +extern unsigned DSPCDP6 (ARMul_State *, unsigned, ARMword); + + +#endif diff --git a/src/core/src/arm/arminit.cpp b/src/core/src/arm/arminit.cpp new file mode 100644 index 000000000..9327f8f6a --- /dev/null +++ b/src/core/src/arm/arminit.cpp @@ -0,0 +1,578 @@ +/*  arminit.c -- ARMulator initialization:  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 "platform.h" +#if EMU_PLATFORM == PLATFORM_LINUX +#include <unistd.h> +#endif + +#include <math.h> + +#include "armdefs.h" +#include "armemu.h" + +/***************************************************************************\ +*                 Definitions for the emulator architecture                 * +\***************************************************************************/ + +void ARMul_EmulateInit (void); +ARMul_State *ARMul_NewState (ARMul_State * state); +void ARMul_Reset (ARMul_State * state); +ARMword ARMul_DoCycle (ARMul_State * state); +unsigned ARMul_DoCoPro (ARMul_State * state); +ARMword ARMul_DoProg (ARMul_State * state); +ARMword ARMul_DoInstr (ARMul_State * state); +void ARMul_Abort (ARMul_State * state, ARMword address); + +unsigned ARMul_MultTable[32] = +	{ 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, +	10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16 +}; +ARMword ARMul_ImmedTable[4096];	/* immediate DP LHS values */ +char ARMul_BitList[256];	/* number of bits in a byte table */ + +//chy 2006-02-22 add test debugmode +extern int debugmode; +extern int remote_interrupt( void ); + + +void arm_dyncom_Abort(ARMul_State * state, ARMword vector) +{ +	ARMul_Abort(state, vector); +} + + +/* ahe-ykl : the following code to initialize user mode  +   code is architecture dependent and probably model dependant. */ + +//#include "skyeye_arch.h" +//#include "skyeye_pref.h" +//#include "skyeye_exec_info.h" +//#include "bank_defs.h" +#include "armcpu.h" +//#include "skyeye_callback.h" + +//void arm_user_mode_init(generic_arch_t * arch_instance) +//{ +//	sky_pref_t *pref = get_skyeye_pref(); +//	 +//	if (pref->user_mode_sim) +//	{ +//		sky_exec_info_t *info = get_skyeye_exec_info(); +//		info->arch_page_size = 0x1000; +//		info->arch_stack_top = 0x1ffffff0;// + 0x401fe7 - 0xff0; /* arbitrary value */ +//		/* stack initial address specific to architecture may be placed here */ +//		 +//		/* we need to mmap the stack space, if we are using skyeye space */ +//		if (info->mmap_access) +//		{ +//			/* get system stack size */ +//			size_t stacksize = 0; +//			pthread_attr_t attr; +//			pthread_attr_init(&attr); +//			pthread_attr_getstacksize(&attr, &stacksize); +//			if (stacksize > info->arch_stack_top) +//			{ +//				printf("arch_stack_top is too low\n"); +//				stacksize = info->arch_stack_top; +//			} +//			 +//			/* Note: Skyeye is occupating 0x400000 to 0x600000 */ +//			/* We do a mmap */ +//			void* ret = mmap( (info->arch_stack_top) - stacksize,  +//				    stacksize + 0x1000 , PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); +//			if (ret == MAP_FAILED){ +//				/* ideally, we should find an empty space until it works */ +//				printf("mmap error, stack couldn't be mapped: errno %d\n", errno); +//				exit(-1); +//			} else { +//				memset(ret, '\0', stacksize); +//				//printf("stack top has been defined at %x size %x\n", (uint32_t) ret + stacksize, stacksize); +//				//info->arch_stack_top = (uint32_t) ret + stacksize; +//			} +//		} +// +//		exec_stack_init(); +//		 +//		ARM_CPU_State* cpu = get_current_cpu(); +//		arm_core_t* core = &cpu->core[0]; +// +//		uint32_t sp = info->initial_sp; +// +//		core->Cpsr = 0x10; /* User mode */ +//		/* FIXME: may need to add thumb */ +//		core->Reg[13] = sp; +//		core->Reg[10] = info->start_data; +//		core->Reg[0] = 0; +//		bus_read(32, sp + 4, &(core->Reg[1])); +//		bus_read(32, sp + 8, &(core->Reg[2])); +//	} +// +//} + +/***************************************************************************\ +*         Call this routine once to set up the emulator's tables.           * +\***************************************************************************/ + +void +ARMul_EmulateInit (void) +{ +	unsigned int i, j; + +	for (i = 0; i < 4096; i++) {	/* the values of 12 bit dp rhs's */ +		ARMul_ImmedTable[i] = ROTATER (i & 0xffL, (i >> 7L) & 0x1eL); +	} + +	for (i = 0; i < 256; ARMul_BitList[i++] = 0);	/* how many bits in LSM */ +	for (j = 1; j < 256; j <<= 1) +		for (i = 0; i < 256; i++) +			if ((i & j) > 0) +				ARMul_BitList[i]++; + +	for (i = 0; i < 256; i++) +		ARMul_BitList[i] *= 4;	/* you always need 4 times these values */ + +} + +/***************************************************************************\ +*            Returns a new instantiation of the ARMulator's state           * +\***************************************************************************/ + +ARMul_State * +ARMul_NewState (ARMul_State *state) +{ +	unsigned i, j; + +	memset (state, 0, sizeof (ARMul_State)); + +	state->Emulate = RUN; +	for (i = 0; i < 16; i++) { +		state->Reg[i] = 0; +		for (j = 0; j < 7; j++) +			state->RegBank[j][i] = 0; +	} +	for (i = 0; i < 7; i++) +		state->Spsr[i] = 0; +	state->Mode = 0; + +	state->CallDebug = FALSE; +	state->Debug = FALSE; +	state->VectorCatch = 0; +	state->Aborted = FALSE; +	state->Reseted = FALSE; +	state->Inted = 3; +	state->LastInted = 3; + +	state->CommandLine = NULL; + +	state->EventSet = 0; +	state->Now = 0; +	state->EventPtr = +		(struct EventNode **) malloc ((unsigned) EVENTLISTSIZE * +					      sizeof (struct EventNode *)); +#if DIFF_STATE +	state->state_log = fopen("/data/state.log", "w"); +	printf("create pc log file.\n"); +#endif +	if (state->EventPtr == NULL) { +		printf ("SKYEYE: ARMul_NewState malloc state->EventPtr error\n"); +		exit(-1); +	} +	for (i = 0; i < EVENTLISTSIZE; i++) +		*(state->EventPtr + i) = NULL; +#if SAVE_LOG +	state->state_log = fopen("/tmp/state.log", "w"); +	printf("create pc log file.\n"); +#else +#if DIFF_LOG +	state->state_log = fopen("/tmp/state.log", "r"); +	printf("loaded pc log file.\n"); +#endif +#endif + +#ifdef ARM61 +	state->prog32Sig = LOW; +	state->data32Sig = LOW; +#else +	state->prog32Sig = HIGH; +	state->data32Sig = HIGH; +#endif + +	state->lateabtSig = HIGH; +	state->bigendSig = LOW; + +	//chy:2003-08-19  +	state->LastTime = 0; +	state->CP14R0_CCD = -1; +	 +	/* ahe-ykl: common function for interpret and dyncom */ +	//sky_pref_t *pref = get_skyeye_pref(); +	//if (pref->user_mode_sim) +	//	register_callback(arm_user_mode_init, Bootmach_callback); + +	memset(&state->exclusive_tag_array[0], 0xFF, sizeof(state->exclusive_tag_array[0]) * 128); +	state->exclusive_access_state = 0; +	//state->cpu = (cpu_config_t *) malloc (sizeof (cpu_config_t)); +	//state->mem_bank = (mem_config_t *) malloc (sizeof (mem_config_t)); +	return (state); +} + +/***************************************************************************\ +*       Call this routine to set ARMulator to model a certain processor     * +\***************************************************************************/ + +void +ARMul_SelectProcessor (ARMul_State * state, unsigned properties) +{ +	if (properties & ARM_Fix26_Prop) { +		state->prog32Sig = LOW; +		state->data32Sig = LOW; +	} +	else { +		state->prog32Sig = HIGH; +		state->data32Sig = HIGH; +	} +/* 2004-05-09 chy +below line sould be in skyeye_mach_XXX.c 's XXX_mach_init function +*/ +	// state->lateabtSig = HIGH; + + +	state->is_v4 = +		(properties & (ARM_v4_Prop | ARM_v5_Prop)) ? HIGH : LOW; +	state->is_v5 = (properties & ARM_v5_Prop) ? HIGH : LOW; +	state->is_v5e = (properties & ARM_v5e_Prop) ? HIGH : LOW; +	state->is_XScale = (properties & ARM_XScale_Prop) ? HIGH : LOW; +	state->is_iWMMXt = (properties & ARM_iWMMXt_Prop) ? HIGH : LOW; +	/* state->is_v6 = LOW */; +	/* jeff.du 2010-08-05 */ +	state->is_v6 = (properties & ARM_v6_Prop) ? HIGH : LOW; +	state->is_ep9312 = (properties & ARM_ep9312_Prop) ? HIGH : LOW; +	//chy 2005-09-19 +	state->is_pxa27x = (properties & ARM_PXA27X_Prop) ? HIGH : LOW; + +	/* shenoubang 2012-3-11 */ +	state->is_v7 = (properties & ARM_v7_Prop) ? HIGH : LOW; + +	/* Only initialse the coprocessor support once we +	   know what kind of chip we are dealing with.  */ +	ARMul_CoProInit (state); + +} + +/***************************************************************************\ +* Call this routine to set up the initial machine state (or perform a RESET * +\***************************************************************************/ + +void +ARMul_Reset (ARMul_State * state) +{ +	//fprintf(stderr,"armul_reset 0: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);   +	state->NextInstr = 0; +	if (state->prog32Sig) { +		state->Reg[15] = 0; +		state->Cpsr = INTBITS | SVC32MODE; +		state->Mode = SVC32MODE; +	} +	else { +		state->Reg[15] = R15INTBITS | SVC26MODE; +		state->Cpsr = INTBITS | SVC26MODE; +		state->Mode = SVC26MODE; +	} +	//fprintf(stderr,"armul_reset 1: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);   +	ARMul_CPSRAltered (state); +	state->Bank = SVCBANK; +	FLUSHPIPE; + +	state->EndCondition = 0; +	state->ErrorCode = 0; + +	//fprintf(stderr,"armul_reset 2: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);   +	state->NresetSig = HIGH; +	state->NfiqSig = HIGH; +	state->NirqSig = HIGH; +	state->NtransSig = (state->Mode & 3) ? HIGH : LOW; +	state->abortSig = LOW; +	state->AbortAddr = 1; + +	state->NumInstrs = 0; +	state->NumNcycles = 0; +	state->NumScycles = 0; +	state->NumIcycles = 0; +	state->NumCcycles = 0; +	state->NumFcycles = 0; + +	//fprintf(stderr,"armul_reset 3: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);   +	mmu_reset (state); +	//fprintf(stderr,"armul_reset 4: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);   + +	//mem_reset (state); /* move to memory/ram.c */ + +	//fprintf(stderr,"armul_reset 5: state->  Cpsr 0x%x, Mode %d\n",state->Cpsr,state->Mode);   +	/*remove later. walimis 03.7.17 */ +	//io_reset(state); +	//lcd_disable(state); + +	/*ywc 2005-04-07 move from ARMul_NewState , because skyeye_config.no_dbct will +	 *be configured in skyeye_option_init and it is called after ARMul_NewState*/ +	state->tea_break_ok = 0; +	state->tea_break_addr = 0; +	state->tea_pc = 0; +#ifdef DBCT +	if (!skyeye_config.no_dbct) { +		//teawater add for arm2x86 2005.02.14------------------------------------------- +		if (arm2x86_init (state)) { +			printf ("SKYEYE: arm2x86_init error\n"); +			skyeye_exit (-1); +		} +		//AJ2D-------------------------------------------------------------------------- +	} +#endif +} + + +/***************************************************************************\ +* Emulate the execution of an entire program.  Start the correct emulator   * +* (Emulate26 for a 26 bit ARM and Emulate32 for a 32 bit ARM), return the   * +* address of the last instruction that is executed.                         * +\***************************************************************************/ + +//teawater add DBCT_TEST_SPEED 2005.10.04--------------------------------------- +#ifdef DBCT_TEST_SPEED +static ARMul_State	*dbct_test_speed_state = NULL; +static void +dbct_test_speed_sig(int signo) +{ +	printf("\n0x%llx %llu\n", dbct_test_speed_state->instr_count, dbct_test_speed_state->instr_count); +	skyeye_exit(0); +} +#endif	//DBCT_TEST_SPEED +//AJ2D-------------------------------------------------------------------------- + +ARMword +ARMul_DoProg (ARMul_State * state) +{ +	ARMword pc = 0; + +	/* +	 * 2007-01-24 removed the term-io functions by Anthony Lee, +	 * moved to "device/uart/skyeye_uart_stdio.c". +	 */ + +//teawater add DBCT_TEST_SPEED 2005.10.04--------------------------------------- +#ifdef DBCT_TEST_SPEED +	{ +		if (!dbct_test_speed_state) { +			//init timer +			struct itimerval	value; +			struct sigaction	act; + +			dbct_test_speed_state = state; +			state->instr_count = 0; +			act.sa_handler = dbct_test_speed_sig; +			act.sa_flags = SA_RESTART; +			//cygwin don't support ITIMER_VIRTUAL or ITIMER_PROF +#ifndef __CYGWIN__ +			if (sigaction(SIGVTALRM, &act, NULL) == -1) { +#else +			if (sigaction(SIGALRM, &act, NULL) == -1) { +#endif	//__CYGWIN__ +				fprintf(stderr, "init timer error.\n"); +				skyeye_exit(-1); +			} +			if (skyeye_config.dbct_test_speed_sec) { +				value.it_value.tv_sec = skyeye_config.dbct_test_speed_sec; +			} +			else { +				value.it_value.tv_sec = DBCT_TEST_SPEED_SEC; +			} +			printf("dbct_test_speed_sec = %ld\n", value.it_value.tv_sec); +			value.it_value.tv_usec = 0; +			value.it_interval.tv_sec = 0;  +			value.it_interval.tv_usec = 0; +#ifndef __CYGWIN__ +			if (setitimer(ITIMER_VIRTUAL, &value, NULL) == -1) { +#else +			if (setitimer(ITIMER_REAL, &value, NULL) == -1) { +#endif	//__CYGWIN__ +				fprintf(stderr, "init timer error.\n"); +				skyeye_exit(-1); +			} +		} +	} +#endif	//DBCT_TEST_SPEED +//AJ2D-------------------------------------------------------------------------- +	state->Emulate = RUN; +	while (state->Emulate != STOP) { +		state->Emulate = RUN; + +		/*ywc 2005-03-31 */ +		if (state->prog32Sig && ARMul_MODE32BIT) { +#ifdef DBCT +			if (skyeye_config.no_dbct) { +				pc = ARMul_Emulate32 (state); +			} +			else { +				pc = ARMul_Emulate32_dbct (state); +			} +#else +			pc = ARMul_Emulate32 (state); +#endif +		} + +		else { +			pc = ARMul_Emulate26 (state); +		} +		//chy 2006-02-22, should test debugmode first +		//chy 2006-04-14, put below codes in ARMul_Emulate +#if 0 +		if(debugmode) +		  if(remote_interrupt()) +			state->Emulate = STOP; +#endif +	} + +	/* +	 * 2007-01-24 removed the term-io functions by Anthony Lee, +	 * moved to "device/uart/skyeye_uart_stdio.c". +	 */ + +	return (pc); +} + +/***************************************************************************\ +* Emulate the execution of one instruction.  Start the correct emulator     * +* (Emulate26 for a 26 bit ARM and Emulate32 for a 32 bit ARM), return the   * +* address of the instruction that is executed.                              * +\***************************************************************************/ + +ARMword +ARMul_DoInstr (ARMul_State * state) +{ +	ARMword pc = 0; + +	state->Emulate = ONCE; + +	/*ywc 2005-03-31 */ +	if (state->prog32Sig && ARMul_MODE32BIT) { +#ifdef DBCT +		if (skyeye_config.no_dbct) { +			pc = ARMul_Emulate32 (state); +		} +		else { +//teawater add compile switch for DBCT GDB RSP function 2005.10.21-------------- +#ifndef DBCT_GDBRSP +			printf("DBCT GDBRSP function switch is off.\n"); +			printf("To use this function, open \"#define DBCT_GDBRSP\" in arch/arm/common/armdefs.h & recompile skyeye.\n"); +			skyeye_exit(-1); +#endif	//DBCT_GDBRSP +//AJ2D-------------------------------------------------------------------------- +			pc = ARMul_Emulate32_dbct (state); +		} +#else +		pc = ARMul_Emulate32 (state); +#endif +	} + +	else +		pc = ARMul_Emulate26 (state); + +	return (pc); +} + +/***************************************************************************\ +* This routine causes an Abort to occur, including selecting the correct    * +* mode, register bank, and the saving of registers.  Call with the          * +* appropriate vector's memory address (0,4,8 ....)                          * +\***************************************************************************/ + +//void +//ARMul_Abort (ARMul_State * state, ARMword vector) +//{ +//	ARMword temp; +//	int isize = INSN_SIZE; +//	int esize = (TFLAG ? 0 : 4); +//	int e2size = (TFLAG ? -4 : 0); +// +//	state->Aborted = FALSE; +// +//	if (state->prog32Sig) +//		if (ARMul_MODE26BIT) +//			temp = R15PC; +//		else +//			temp = state->Reg[15]; +//	else +//		temp = R15PC | ECC | ER15INT | EMODE; +// +//	switch (vector) { +//	case ARMul_ResetV:	/* RESET */ +//		SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE, +//			  0); +//		break; +//	case ARMul_UndefinedInstrV:	/* Undefined Instruction */ +//		SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE, +//			  isize); +//		break; +//	case ARMul_SWIV:	/* Software Interrupt */ +//		SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE, +//			  isize); +//		break; +//	case ARMul_PrefetchAbortV:	/* Prefetch Abort */ +//		state->AbortAddr = 1; +//		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, +//			  esize); +//		break; +//	case ARMul_DataAbortV:	/* Data Abort */ +//		SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, +//			  e2size); +//		break; +//	case ARMul_AddrExceptnV:	/* Address Exception */ +//		SETABORT (IBIT, SVC26MODE, isize); +//		break; +//	case ARMul_IRQV:	/* IRQ */ +//		//chy 2003-09-02 the if sentence seems no use +//#if 0 +//		if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) +//		    || (temp & ARMul_CP13_R0_IRQ)) +//#endif +//			SETABORT (IBIT, +//				  state->prog32Sig ? IRQ32MODE : IRQ26MODE, +//				  esize); +//		break; +//	case ARMul_FIQV:	/* FIQ */ +//		//chy 2003-09-02 the if sentence seems no use +//#if 0 +//		if (!state->is_XScale || !state->CPRead[13] (state, 0, &temp) +//		    || (temp & ARMul_CP13_R0_FIQ)) +//#endif +//			SETABORT (INTBITS, +//				  state->prog32Sig ? FIQ32MODE : FIQ26MODE, +//				  esize); +//		break; +//	} +// +//	if (ARMul_MODE32BIT) { +//		if (state->mmu.control & CONTROL_VECTOR) +//			vector += 0xffff0000;	//for v4 high exception  address +//		if (state->vector_remap_flag) +//			vector += state->vector_remap_addr; /* support some remap function in LPC processor */ +//		ARMul_SetR15 (state, vector); +//	} +//	else +//		ARMul_SetR15 (state, R15CCINTMODE | vector); +//} diff --git a/src/core/src/arm/armmmu.cpp b/src/core/src/arm/armmmu.cpp new file mode 100644 index 000000000..5ba81b52a --- /dev/null +++ b/src/core/src/arm/armmmu.cpp @@ -0,0 +1,241 @@ +/* +    armmmu.c - Memory Management Unit emulation. +    ARMulator extensions for the ARM7100 family. +    Copyright (C) 1999  Ben Williamson + +    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 <assert.h> +#include <string.h> +#include "armdefs.h" +/* two header for arm disassemble */ +//#include "skyeye_arch.h" +#include "armcpu.h" + + +extern mmu_ops_t xscale_mmu_ops; +exception_t arm_mmu_write(short size, u32 addr, uint32_t *value); +exception_t arm_mmu_read(short size, u32 addr, uint32_t *value); +#define MMU_OPS (state->mmu.ops) +ARMword skyeye_cachetype = -1; + +int +mmu_init (ARMul_State * state) +{ +	int ret; + +	state->mmu.control = 0x70; +	state->mmu.translation_table_base = 0xDEADC0DE; +	state->mmu.domain_access_control = 0xDEADC0DE; +	state->mmu.fault_status = 0; +	state->mmu.fault_address = 0; +	state->mmu.process_id = 0; + +	switch (state->cpu->cpu_val & state->cpu->cpu_mask) { +	case SA1100: +	case SA1110: +		SKYEYE_INFO("SKYEYE: use sa11xx mmu ops\n"); +		state->mmu.ops = sa_mmu_ops; +		break; +	case PXA250: +	case PXA270:		//xscale +		SKYEYE_INFO ("SKYEYE: use xscale mmu ops\n"); +		state->mmu.ops = xscale_mmu_ops; +		break; +	case 0x41807200:	//arm720t +	case 0x41007700:	//arm7tdmi +	case 0x41007100:	//arm7100 +		SKYEYE_INFO ( "SKYEYE: use arm7100 mmu ops\n"); +		state->mmu.ops = arm7100_mmu_ops; +		break; +	case 0x41009200: +		SKYEYE_INFO ("SKYEYE: use arm920t mmu ops\n"); +		state->mmu.ops = arm920t_mmu_ops; +		break; +	case 0x41069260: +		SKYEYE_INFO ("SKYEYE: use arm926ejs mmu ops\n"); +		state->mmu.ops = arm926ejs_mmu_ops; +		break; +	/* case 0x560f5810: */ +	case 0x0007b000: +		SKYEYE_INFO ("SKYEYE: use arm11jzf-s mmu ops\n"); +		state->mmu.ops = arm1176jzf_s_mmu_ops; +		break; + +	case 0xc090: +		SKYEYE_INFO ("SKYEYE: use cortex_a9 mmu ops\n"); +		state->mmu.ops = cortex_a9_mmu_ops; +		break; +	default: +		fprintf (stderr, +			 "SKYEYE: armmmu.c : mmu_init: unknown cpu_val&cpu_mask 0x%x\n", +			 state->cpu->cpu_val & state->cpu->cpu_mask); +		skyeye_exit (-1); +		break; + +	}; +	ret = state->mmu.ops.init (state); +	state->mmu_inited = (ret == 0); +	/* initialize mmu_read and mmu_write for disassemble */ +	skyeye_config_t *config  = get_current_config(); +	generic_arch_t *arch_instance = get_arch_instance(config->arch->arch_name); +	arch_instance->mmu_read = arm_mmu_read; +	arch_instance->mmu_write = arm_mmu_write; + +	return ret; +} + +int +mmu_reset (ARMul_State * state) +{ +	if (state->mmu_inited) +		mmu_exit (state); +	return mmu_init (state); +} + +void +mmu_exit (ARMul_State * state) +{ +	MMU_OPS.exit (state); +	state->mmu_inited = 0; +} + +fault_t +mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data) +{ +	return MMU_OPS.read_byte (state, virt_addr, data); +}; + +fault_t +mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data) +{ +	return MMU_OPS.read_halfword (state, virt_addr, data); +}; + +fault_t +mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data) +{ +	return MMU_OPS.read_word (state, virt_addr, data); +}; + +fault_t +mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data) +{ +	fault_t fault; +	//static int count = 0; +	//count ++; +	fault = MMU_OPS.write_byte (state, virt_addr, data); +	return fault; +} + +fault_t +mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data) +{ +	fault_t fault; +	//static int count = 0; +	//count ++; +	fault = MMU_OPS.write_halfword (state, virt_addr, data); +	return fault; +} + +fault_t +mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data) +{ +	fault_t fault; +	fault = MMU_OPS.write_word (state, virt_addr, data); + +	/*used for debug for MMU* + +	   if (!fault){ +	   ARMword tmp; + +	   if (mmu_read_word(state, virt_addr, &tmp)){ +	   err_msg("load back\n"); +	   exit(-1); +	   }else{ +	   if (tmp != data){ +	   err_msg("load back not equal %d %x\n", count, virt_addr); +	   } +	   } +	   } +	 */ + +	return fault; +}; + +fault_t +mmu_load_instr (ARMul_State * state, ARMword virt_addr, ARMword * instr) +{ +	return MMU_OPS.load_instr (state, virt_addr, instr); +} + +ARMword +mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value) +{ +	return MMU_OPS.mrc (state, instr, value); +} + +void +mmu_mcr (ARMul_State * state, ARMword instr, ARMword value) +{ +	MMU_OPS.mcr (state, instr, value); +} + +/*ywc 20050416*/ +int +mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr) +{ +	return (MMU_OPS.v2p_dbct (state, virt_addr, phys_addr)); +} + +/* dis_mmu_read for disassemble */ +exception_t arm_mmu_read(short size, generic_address_t addr, uint32_t * value) +{ +	ARMul_State *state; +	ARM_CPU_State *cpu = get_current_cpu(); +	state = &cpu->core[0]; +	switch(size){ +	case 8: +		MMU_OPS.read_byte (state, addr, value); +		break; +	case 16: +	case 32: +		break; +	default: +		printf("In %s error size %d Line %d\n", __func__, size, __LINE__); +		break; +	} +	return No_exp; +} +/* dis_mmu_write for disassemble */ +exception_t arm_mmu_write(short size, generic_address_t addr, uint32_t *value) +{ +	ARMul_State *state; +	ARM_CPU_State *cpu = get_current_cpu(); +		state = &cpu->core[0]; +	switch(size){ +	case 8: +		MMU_OPS.write_byte (state, addr, value); +		break; +	case 16: +	case 32: +		break; +	default: +		printf("In %s error size %d Line %d\n", __func__, size, __LINE__); +		break; +	} +	return No_exp; +} diff --git a/src/core/src/arm/armmmu.h b/src/core/src/arm/armmmu.h new file mode 100644 index 000000000..bf2904f63 --- /dev/null +++ b/src/core/src/arm/armmmu.h @@ -0,0 +1,254 @@ +/* +    armmmu.c - Memory Management Unit emulation. +    ARMulator extensions for the ARM7100 family. +    Copyright (C) 1999  Ben Williamson + +    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 +*/ + +#ifndef _ARMMMU_H_ +#define _ARMMMU_H_ + + +#define WORD_SHT			2 +#define WORD_SIZE			(1<<WORD_SHT) +/* The MMU is accessible with MCR and MRC operations to copro 15: */ + +#define MMU_COPRO			(15) + +/* Register numbers in the MMU: */ + +typedef enum mmu_regnum_t +{ +	MMU_ID = 0, +	MMU_CONTROL = 1, +	MMU_TRANSLATION_TABLE_BASE = 2, +	MMU_DOMAIN_ACCESS_CONTROL = 3, +	MMU_FAULT_STATUS = 5, +	MMU_FAULT_ADDRESS = 6, +	MMU_CACHE_OPS = 7, +	MMU_TLB_OPS = 8, +	MMU_CACHE_LOCKDOWN = 9, +	MMU_TLB_LOCKDOWN = 10, +	MMU_PID = 13, + +	/*MMU_V4 */ +	MMU_V4_CACHE_OPS = 7, +	MMU_V4_TLB_OPS = 8, + +	/*MMU_V3 */ +	MMU_V3_FLUSH_TLB = 5, +	MMU_V3_FLUSH_TLB_ENTRY = 6, +	MMU_V3_FLUSH_CACHE = 7, + +	/*MMU Intel SA-1100 */ +	MMU_SA_RB_OPS = 9, +	MMU_SA_DEBUG = 14, +	MMU_SA_CP15_R15 = 15, +	//chy 2003-08-24 +	/*Intel xscale CP15 */ +	XSCALE_CP15_CACHE_TYPE = 0, +	XSCALE_CP15_AUX_CONTROL = 1, +	XSCALE_CP15_COPRO_ACCESS = 15, + +} mmu_regnum_t; + +/* Bits in the control register */ + +#define CONTROL_MMU			(1<<0) +#define CONTROL_ALIGN_FAULT		(1<<1) +#define CONTROL_CACHE			(1<<2) +#define CONTROL_DATA_CACHE		(1<<2) +#define CONTROL_WRITE_BUFFER		(1<<3) +#define CONTROL_BIG_ENDIAN		(1<<7) +#define CONTROL_SYSTEM			(1<<8) +#define CONTROL_ROM			(1<<9) +#define CONTROL_UNDEFINED               (1<<10) +#define CONTROL_BRANCH_PREDICT          (1<<11) +#define CONTROL_INSTRUCTION_CACHE       (1<<12) +#define CONTROL_VECTOR                  (1<<13) +#define CONTROL_RR                      (1<<14) +#define CONTROL_L4                      (1<<15) +#define CONTROL_XP                      (1<<23) +#define CONTROL_EE                      (1<<25) + +/*Macro defines for MMU state*/ +#define MMU_CTL (state->mmu.control) +#define MMU_Enabled (state->mmu.control & CONTROL_MMU) +#define MMU_Disabled (!(MMU_Enabled)) +#define MMU_Aligned (state->mmu.control & CONTROL_ALIGN_FAULT) + +#define MMU_ICacheEnabled (MMU_CTL & CONTROL_INSTRUCTION_CACHE) +#define MMU_ICacheDisabled (!(MMU_ICacheDisabled)) + +#define MMU_DCacheEnabled (MMU_CTL & CONTROL_DATA_CACHE) +#define MMU_DCacheDisabled (!(MMU_DCacheEnabled)) + +#define MMU_CacheEnabled (MMU_CTL & CONTROL_CACHE) +#define MMU_CacheDisabled (!(MMU_CacheEnabled)) + +#define MMU_WBEnabled (MMU_CTL & CONTROL_WRITE_BUFFER) +#define MMU_WBDisabled (!(MMU_WBEnabled)) + +/*virt_addr exchange according to CP15.R13(process id virtul mapping)*/ +#define PID_VA_MAP_MASK	0xfe000000 +#define mmu_pid_va_map(va) ({\ +	ARMword ret; \ +	if ((va) & PID_VA_MAP_MASK)\ +		ret = (va); \ +	else \ +		ret = ((va) | (state->mmu.process_id & PID_VA_MAP_MASK));\ +	ret;\ +}) + + +/* FS[3:0] in the fault status register: */ + +typedef enum fault_t +{ +	NO_FAULT = 0x0, +	ALIGNMENT_FAULT = 0x1, + +	SECTION_TRANSLATION_FAULT = 0x5, +	PAGE_TRANSLATION_FAULT = 0x7, +	SECTION_DOMAIN_FAULT = 0x9, +	PAGE_DOMAIN_FAULT = 0xB, +	SECTION_PERMISSION_FAULT = 0xD, +	SUBPAGE_PERMISSION_FAULT = 0xF, + +	/* defined by skyeye */ +	TLB_READ_MISS = 0x30, +	TLB_WRITE_MISS = 0x40, + +} fault_t; + +typedef struct mmu_ops_s +{ +	/*initilization */ +	int (*init) (ARMul_State * state); +	/*free on exit */ +	void (*exit) (ARMul_State * state); +	/*read byte data */ +	  fault_t (*read_byte) (ARMul_State * state, ARMword va, +				ARMword * data); +	/*write byte data */ +	  fault_t (*write_byte) (ARMul_State * state, ARMword va, +				 ARMword data); +	/*read halfword data */ +	  fault_t (*read_halfword) (ARMul_State * state, ARMword va, +				    ARMword * data); +	/*write halfword data */ +	  fault_t (*write_halfword) (ARMul_State * state, ARMword va, +				     ARMword data); +	/*read word data */ +	  fault_t (*read_word) (ARMul_State * state, ARMword va, +				ARMword * data); +	/*write word data */ +	  fault_t (*write_word) (ARMul_State * state, ARMword va, +				 ARMword data); +	/*load instr */ +	  fault_t (*load_instr) (ARMul_State * state, ARMword va, +				 ARMword * instr); +	/*mcr */ +	  ARMword (*mcr) (ARMul_State * state, ARMword instr, ARMword val); +	/*mrc */ +	  ARMword (*mrc) (ARMul_State * state, ARMword instr, ARMword * val); + +	/*ywc 2005-04-16 convert virtual address to physics address */ +	int (*v2p_dbct) (ARMul_State * state, ARMword virt_addr, +			 ARMword * phys_addr); +} mmu_ops_t; + + +#include "mmu/tlb.h" +#include "mmu/rb.h" +#include "mmu/wb.h" +#include "mmu/cache.h" + +/*special process mmu.h*/ +//#include "mmu/sa_mmu.h" +//#include "mmu/arm7100_mmu.h" +//#include "mmu/arm920t_mmu.h" +//#include "mmu/arm926ejs_mmu.h" +#include "mmu/arm1176jzf_s_mmu.h" +//#include "mmu/cortex_a9_mmu.h" + +typedef struct mmu_state_t +{ +	ARMword control; +	ARMword translation_table_base; +/* dyf 201-08-11 for arm1176 */ +	ARMword auxiliary_control; +	ARMword coprocessor_access_control; +	ARMword translation_table_base0; +	ARMword translation_table_base1; +	ARMword translation_table_ctrl; +/* arm1176 end */ + +	ARMword domain_access_control; +	ARMword fault_status; +	ARMword fault_statusi;  /* prefetch fault status */ +	ARMword fault_address; +	ARMword last_domain; +	ARMword process_id; +	ARMword context_id; +	ARMword thread_uro_id; +	ARMword cache_locked_down; +	ARMword tlb_locked_down; +//chy 2003-08-24 for xscale +	ARMword cache_type;	// 0 +	ARMword aux_control;	// 1 +	ARMword copro_access;	// 15 + +	mmu_ops_t ops; +	//union +	//{ +		//sa_mmu_t sa_mmu; +		//arm7100_mmu_t arm7100_mmu; +		//arm920t_mmu_t arm920t_mmu; +		//arm926ejs_mmu_t arm926ejs_mmu; +	//} u; +} mmu_state_t; + +int mmu_init (ARMul_State * state); +int mmu_reset (ARMul_State * state); +void mmu_exit (ARMul_State * state); + +fault_t mmu_read_word (ARMul_State * state, ARMword virt_addr, +		       ARMword * data); +fault_t mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data); +fault_t mmu_load_instr (ARMul_State * state, ARMword virt_addr, +			ARMword * instr); + +ARMword mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value); +void mmu_mcr (ARMul_State * state, ARMword instr, ARMword value); + +/*ywc 20050416*/ +int mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, +		  ARMword * phys_addr); + +fault_t +mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data); +fault_t +mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data); +fault_t +mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data); +fault_t +mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data); +fault_t +mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data); +fault_t +mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data); +#endif /* _ARMMMU_H_ */ diff --git a/src/core/src/arm/armos.h b/src/core/src/arm/armos.h new file mode 100644 index 000000000..4b58801ad --- /dev/null +++ b/src/core/src/arm/armos.h @@ -0,0 +1,138 @@ +/*  armos.h -- ARMulator OS definitions:  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 "bank_defs.h" +//#include "dyncom/defines.h" + +//typedef struct mmap_area{ +//	mem_bank_t bank; +//	void *mmap_addr; +//	struct mmap_area *next; +//}mmap_area_t; + +#if FAST_MEMORY +/* in user mode, mmap_base will be on initial brk, +   set at the first mmap request */ +#define mmap_base -1 +#else +#define mmap_base 0x50000000 +#endif +static long mmap_next_base = mmap_base; + +//static mmap_area_t* new_mmap_area(int sim_addr, int len); +static char mmap_mem_write(short size, int addr, uint32_t value); +static char mmap_mem_read(short size, int addr, uint32_t * value); + +/***************************************************************************\ +*                               SWI numbers                                 * +\***************************************************************************/ + +#define SWI_Syscall                0x0 +#define SWI_Exit                   0x1 +#define SWI_Read                   0x3 +#define SWI_Write                  0x4 +#define SWI_Open                   0x5 +#define SWI_Close                  0x6 +#define SWI_Seek                   0x13 +#define SWI_Rename                 0x26 +#define SWI_Break                  0x11 + +#define SWI_Times		   0x2b +#define SWI_Brk			   0x2d + +#define SWI_Mmap                   0x5a +#define SWI_Munmap                 0x5b +#define SWI_Mmap2                  0xc0 + +#define SWI_GetUID32               0xc7 +#define SWI_GetGID32               0xc8 +#define SWI_GetEUID32              0xc9 +#define SWI_GetEGID32              0xca + +#define SWI_ExitGroup		   0xf8 + +#if 0 +#define SWI_Time                   0xd +#define SWI_Clock                  0x61 +#define SWI_Time                   0x63 +#define SWI_Remove                 0x64 +#define SWI_Rename                 0x65 +#define SWI_Flen                   0x6c +#endif + +#define SWI_Uname		   0x7a +#define SWI_Fcntl                  0xdd  +#define SWI_Fstat64  		   0xc5 +#define SWI_Gettimeofday           0x4e +#define SWI_Set_tls                0xf0005 + +#define SWI_Breakpoint             0x180000	/* see gdb's tm-arm.h */ + +/***************************************************************************\ +*                             SWI structures                                * +\***************************************************************************/ + +/* Arm binaries (for now) only support 32 bit, and expect to receive +   32-bit compliant structure in return of a systen call. Because +   we use host system calls to emulate system calls, the returned +   structure can be 32-bit compliant or 64-bit compliant, depending +   on the OS running skyeye. Therefore, we need a fixed size structure +   adapted to arm.*/ + +/* Borrowed from qemu */ +struct target_stat64 { +	unsigned short	st_dev; +	unsigned char	__pad0[10]; +	uint32_t	__st_ino; +	unsigned int	st_mode; +	unsigned int	st_nlink; +	uint32_t	st_uid; +	uint32_t	st_gid; +	unsigned short	st_rdev; +	unsigned char	__pad3[10]; +	unsigned char	__pad31[4]; +	long long	st_size; +	uint32_t	st_blksize; +	unsigned char	__pad32[4]; +	uint32_t	st_blocks; +	uint32_t	__pad4; +	uint32_t	st32_atime; +	uint32_t	__pad5; +	uint32_t	st32_mtime; +	uint32_t	__pad6; +	uint32_t	st32_ctime; +	uint32_t	__pad7; +	unsigned long long	st_ino; +};// __attribute__((packed)); + +struct target_tms32 { +    uint32_t tms_utime; +    uint32_t tms_stime; +    uint32_t tms_cutime; +    uint32_t tms_cstime; +}; + +struct target_timeval32 { +	uint32_t tv_sec;     /* seconds */ +	uint32_t tv_usec;    /* microseconds */ +}; + +struct target_timezone32 { +	int32_t tz_minuteswest;     /* minutes west of Greenwich */ +	int32_t tz_dsttime;         /* type of DST correction */ +}; + diff --git a/src/core/src/arm/mmu/arm1176jzf_s_mmu.c b/src/core/src/arm/mmu/arm1176jzf_s_mmu.c new file mode 100644 index 000000000..5d8c4590a --- /dev/null +++ b/src/core/src/arm/mmu/arm1176jzf_s_mmu.c @@ -0,0 +1,1165 @@ +/* +    arm1176jzf_s_mmu.c - ARM920T Memory Management Unit emulation. +    Copyright (C) 2003 Skyeye Develop Group +    for help please send mail to <skyeye-developer@lists.gro.clinux.org> + +    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 <assert.h> +#include <string.h> +#include <stdint.h> +#include <skyeye_ram.h> + +#include "armdefs.h" +#include "bank_defs.h" +#if 0 +#define TLB_SIZE 1024 * 1024 +#define ASID 255 +static uint32_t tlb_entry_array[TLB_SIZE][ASID]; +static inline void invalidate_all_tlb(ARMul_State *state){ +	memset(&tlb_entry_array[0], 0xFF, sizeof(uint32_t) * TLB_SIZE * ASID); +} +static inline void invalidate_by_mva(ARMul_State *state, ARMword va){ +	memset(&tlb_entry_array[va >> 12][va & 0xFF], 0xFF, sizeof(uint32_t)); +	return; +} +static inline void invalidate_by_asid(ARMul_State *state, ARMword asid){ +	int i; +	for(i = 0; i < TLB_SIZE; i++) +		memset(&tlb_entry_array[i][asid & 0xFF], 0xFF, sizeof(uint32_t)); +	return; +} + +static uint32_t get_phys_page(ARMul_State* state, ARMword va){ +	uint32_t phys_page = tlb_entry_array[va >> 12][state->mmu.context_id & 0xFF]; +	//printf("In %s, for va=0x%x, page=0x%x\n", __func__, va, phys_page); +	return phys_page; +} + +static inline void insert_tlb(ARMul_State* state, ARMword va, ARMword pa){ +	//printf("In %s, insert va=0x%x, pa=0x%x\n", __FUNCTION__, va, pa); +	//printf("In %s, insert va=0x%x, va>>12=0x%x, pa=0x%x, pa>>12=0x%x\n", __FUNCTION__, va, va >> 12, pa, pa >> 12); +	tlb_entry_array[va >> 12][state->mmu.context_id & 0xFF] = pa >> 12; + +	return; +} +#endif +#define BANK0_START 0x50000000 +static void* mem_ptr = NULL; +//static void mem_read_raw(uint32_t offset, uint32_t &value, int size) +static void mem_read_raw(int size, uint32_t offset, uint32_t *value) +{ +#if 0 +	if(mem_ptr == NULL) +		mem_ptr = (uint8_t*)get_dma_addr(BANK0_START); +	//printf("In %s, offset=0x%x, mem_ptr=0x%llx\n", __FUNCTION__, offset, mem_ptr); +	if(offset >= 0x50000000 && offset < 0x70000000){ +		mem_read(size, offset, value);	 +	}	 +	else{ +		bus_read(size, offset, value); +	} +#endif +	bus_read(size, offset, value); +} + +//static void mem_write_raw(uint32_t offset, uint32_t value, int size) +static void mem_write_raw(int size, uint32_t offset, uint32_t value) +{ +#if 0 +	if(mem_ptr == NULL) +		mem_ptr = (uint8_t*)get_dma_addr(BANK0_START); +	//printf("In %s, offset=0x%x, mem_ptr=0x%llx\n", __FUNCTION__, offset, mem_ptr); +	if(offset >= 0x50000000 && offset < 0x70000000){ +		mem_write(size, offset, value); +	} +	else{ +		bus_write(size, offset, value); +	} +#endif +	bus_write(size, offset, value); +} + +static int exclusive_detect(ARMul_State* state, ARMword addr){ +	int i; +	#if 0 +	for(i = 0; i < 128; i++){ +		if(state->exclusive_tag_array[i] == addr) +			return 0; +	} +	#endif +	if(state->exclusive_tag_array[0] == addr) +		return 0; +	else +		return -1; +} + +static void add_exclusive_addr(ARMul_State* state, ARMword addr){ +	int i; +	#if 0 +	for(i = 0; i < 128; i++){ +		if(state->exclusive_tag_array[i] == 0xffffffff){ +			state->exclusive_tag_array[i] = addr; +			//printf("In %s, add  addr 0x%x\n", __func__, addr); +			return; +		} +	} +	printf("In %s ,can not monitor the addr, out of array\n", __FUNCTION__); +	#endif +	state->exclusive_tag_array[0] = addr; +	return; +} + +static void remove_exclusive(ARMul_State* state, ARMword addr){ +	#if 0 +	int i; +	for(i = 0; i < 128; i++){ +		if(state->exclusive_tag_array[i] == addr){ +			state->exclusive_tag_array[i] = 0xffffffff; +			//printf("In %s, remove  addr 0x%x\n", __func__, addr); +			return; +		} +	} +	#endif +	state->exclusive_tag_array[0] = 0xFFFFFFFF; +} + +/* This function encodes table 8-2 Interpreting AP bits, +   returning non-zero if access is allowed. */ +static int +check_perms (ARMul_State *state, int ap, int read) +{ +	int s, r, user; + +	s = state->mmu.control & CONTROL_SYSTEM; +	r = state->mmu.control & CONTROL_ROM; +	/* chy 2006-02-15 , should consider system mode, don't conside 26bit mode */ +//    printf("ap is %x, user is %x, s is %x, read is %x\n", ap, user, s, read); +//    printf("mode is %x\n", state->Mode); +	user = (state->Mode == USER32MODE) || (state->Mode == USER26MODE) || (state->Mode == SYSTEM32MODE); + +	switch (ap) { +	case 0: +		return read && ((s && !user) || r); +	case 1: +		return !user; +	case 2: +		return read || !user; +	case 3: +		return 1; +	} +	return 0; +} + +#if 0 +fault_t +check_access (ARMul_State *state, ARMword virt_addr, tlb_entry_t *tlb, +	      int read) +{ +	int access; + +	state->mmu.last_domain = tlb->domain; +	access = (state->mmu.domain_access_control >> (tlb->domain * 2)) & 3; +	if ((access == 0) || (access == 2)) { +		/* It's unclear from the documentation whether this +		   should always raise a section domain fault, or if +		   it should be a page domain fault in the case of an +		   L1 that describes a page table.  In the ARM710T +		   datasheets, "Figure 8-9: Sequence for checking faults" +		   seems to indicate the former, while "Table 8-4: Priority +		   encoding of fault status" gives a value for FS[3210] in +		   the event of a domain fault for a page.  Hmm. */ +		return SECTION_DOMAIN_FAULT; +	} +	if (access == 1) { +		/* client access - check perms */ +		int subpage, ap; +#if 0 +		switch (tlb->mapping) { +			/*ks 2004-05-09 +			 *   only for XScale +			 *   Extend Small Page(ESP) Format +			 *   31-12 bits    the base addr of ESP +			 *   11-10 bits    SBZ +			 *   9-6   bits    TEX +			 *   5-4   bits    AP +			 *   3     bit     C +			 *   2     bit     B +			 *   1-0   bits    11 +			 * */ +		case TLB_ESMALLPAGE:	/* xj */ +			subpage = 0; +			/* printf("TLB_ESMALLPAGE virt_addr=0x%x  \n",virt_addr ); */ +			break; + +		case TLB_TINYPAGE: +			subpage = 0; +			/* printf("TLB_TINYPAGE virt_addr=0x%x  \n",virt_addr ); */ +			break; + +		case TLB_SMALLPAGE: +			subpage = (virt_addr >> 10) & 3; +			break; +		case TLB_LARGEPAGE: +			subpage = (virt_addr >> 14) & 3; +			break; +		case TLB_SECTION: +			subpage = 3; +			break; +		default: +			assert (0); +			subpage = 0;	/* cleans a warning */ +		} +		ap = (tlb->perms >> (subpage * 2 + 4)) & 3; +		if (!check_perms (state, ap, read)) { +			if (tlb->mapping == TLB_SECTION) { +				return SECTION_PERMISSION_FAULT; +			} else { +				return SUBPAGE_PERMISSION_FAULT; +			} +		} +#endif +	} else {			/* access == 3 */ +		/* manager access - don't check perms */ +	} +	return NO_FAULT; +} +#endif + +#if 0 +fault_t +mmu_translate (ARMul_State *state, ARMword virt_addr, ARMword *phys_addr) +#endif + +/*  ap: AP bits value. + *  sop: section or page description  0:section 1:page + */ +fault_t +mmu_translate (ARMul_State *state, ARMword virt_addr, ARMword *phys_addr, int *ap, int *sop) +{ +	{ +		/* walk the translation tables */ +		ARMword l1addr, l1desc; +		if (state->mmu.translation_table_ctrl && virt_addr << state->mmu.translation_table_ctrl >> (32 - state->mmu.translation_table_ctrl - 1)) { +			l1addr = state->mmu.translation_table_base1; +			l1addr = (((l1addr >> 14) << 14) | (virt_addr >> 18)) & ~3; +		} else { +			l1addr = state->mmu.translation_table_base0; +			l1addr = (((l1addr >> (14 - state->mmu.translation_table_ctrl)) << (14 - state->mmu.translation_table_ctrl)) | (virt_addr << state->mmu.translation_table_ctrl) >> (18 + state->mmu.translation_table_ctrl)) & ~3; +		} + +		/* l1desc = mem_read_word (state, l1addr); */ +		if(state->space.conf_obj != NULL) +			state->space.read(state->space.conf_obj, l1addr, &l1desc, 4); +		else +			mem_read_raw(32, l1addr, &l1desc); +        #if 0 +        if (virt_addr == 0xc000d2bc) { +                printf("mmu_control is %x\n", state->mmu.translation_table_ctrl); +                printf("mmu_table_0 is %x\n", state->mmu.translation_table_base0); +                printf("mmu_table_1 is %x\n", state->mmu.translation_table_base1); +                printf("l1addr is %x l1desc is %x\n", l1addr, l1desc); + //               exit(-1); +        } +        #endif +		switch (l1desc & 3) { +		case 0: +		case 3: +			/* +			 * according to Figure 3-9 Sequence for checking faults in arm manual, +			 * section translation fault should be returned here. +			 */ +			{ +				return SECTION_TRANSLATION_FAULT; +			} +		case 1: +			/* coarse page table */ +			{ +				ARMword l2addr, l2desc; + + +				l2addr = l1desc & 0xFFFFFC00; +				l2addr = (l2addr | +					  ((virt_addr & 0x000FF000) >> 10)) & +					~3; +				if(state->space.conf_obj != NULL) +					state->space.read(state->space.conf_obj, l2addr, &l2desc, 4); +				else +					mem_read_raw(32, l2addr, &l2desc); +				/* chy 2003-09-02 for xscale */ +				*ap = (l2desc >> 4) & 0x3; +				*sop = 1;	/* page */ + +				switch (l2desc & 3) { +				case 0: +					return PAGE_TRANSLATION_FAULT; +					break; +				case 1: +					*phys_addr = (l2desc & 0xFFFF0000) | (virt_addr & 0x0000FFFF); +					break; +				case 2: +				case 3: +					*phys_addr = (l2desc & 0xFFFFF000) | (virt_addr & 0x00000FFF); +					break; + +				} +			} +			break; +		case 2: +			/* section */ + +			*ap = (l1desc >> 10) & 3; +			*sop = 0; 	/* section */ +            #if 0 +            if (virt_addr == 0xc000d2bc) { +                    printf("mmu_control is %x\n", state->mmu.translation_table_ctrl); +                    printf("mmu_table_0 is %x\n", state->mmu.translation_table_base0); +                    printf("mmu_table_1 is %x\n", state->mmu.translation_table_base1); +                    printf("l1addr is %x l1desc is %x\n", l1addr, l1desc); +//                    printf("l2addr is %x l2desc is %x\n", l2addr, l2desc); +                    printf("ap is %x, sop is %x\n", *ap, *sop); +                    printf("mode is %d\n", state->Mode); +//                      exit(-1); +            } +            #endif + +            if (l1desc & 0x30000) +				*phys_addr = (l1desc & 0xFF000000) | (virt_addr & 0x00FFFFFF); +			else +				*phys_addr = (l1desc & 0xFFF00000) | (virt_addr & 0x000FFFFF); +			break; +		} +	} +	return NO_FAULT; +} + + +static fault_t arm1176jzf_s_mmu_write (ARMul_State *state, ARMword va, +				  ARMword data, ARMword datatype); +static fault_t arm1176jzf_s_mmu_read (ARMul_State *state, ARMword va, +				 ARMword *data, ARMword datatype); + +int +arm1176jzf_s_mmu_init (ARMul_State *state) +{ +	state->mmu.control = 0x50078; +	state->mmu.translation_table_base = 0xDEADC0DE; +	state->mmu.domain_access_control = 0xDEADC0DE; +	state->mmu.fault_status = 0; +	state->mmu.fault_address = 0; +	state->mmu.process_id = 0; +	state->mmu.context_id = 0; +	state->mmu.thread_uro_id = 0; +	//invalidate_all_tlb(state); + +	return No_exp; +} + +void +arm1176jzf_s_mmu_exit (ARMul_State *state) +{ +} + + +static fault_t +arm1176jzf_s_mmu_load_instr (ARMul_State *state, ARMword va, ARMword *instr) +{ +	fault_t fault; +	int c;			/* cache bit */ +	ARMword pa;		/* physical addr */ +	ARMword perm;		/* physical addr access permissions */ +	int ap, sop; + +	static int debug_count = 0;	/* used for debug */ + +	d_msg ("va = %x\n", va); + +	va = mmu_pid_va_map (va); +	if (MMU_Enabled) { +//            printf("MMU enabled.\n"); +//            sleep(1); +            /* align check */ +		if ((va & (WORD_SIZE - 1)) && MMU_Aligned) { +			d_msg ("align\n"); +			return ALIGNMENT_FAULT; +		} else +			va &= ~(WORD_SIZE - 1); + +		/* translate tlb */ +		fault = mmu_translate (state, va, &pa, &ap, &sop); +		if (fault) { +			d_msg ("translate\n"); +			printf("va=0x%x, icounter=%lld, fault=%d\n", va, state->NumInstrs, fault); +			return fault; +		} + + +		/* no tlb, only check permission */ +		if (!check_perms(state, ap, 1)) { +			if (sop == 0) { +				return SECTION_PERMISSION_FAULT; +			} else { +				return SUBPAGE_PERMISSION_FAULT; +			} +		} + +#if 0 +		/*check access */ +		fault = check_access (state, va, tlb, 1); +		if (fault) { +			d_msg ("check_fault\n"); +			return fault; +		} +#endif +	} + +	/*if MMU disabled or C flag is set alloc cache */ +	if (MMU_Disabled) { +//            printf("MMU disabled.\n"); +//            sleep(1); +		pa = va; +	} +	if(state->space.conf_obj == NULL) +		state->space.read(state->space.conf_obj, pa, instr, 4); +	else +		mem_read_raw(32, pa, instr); + +	return 0; +} + +static fault_t +arm1176jzf_s_mmu_read_byte (ARMul_State *state, ARMword virt_addr, ARMword *data) +{ +	/* ARMword temp,offset; */ +	fault_t fault; +	fault = arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE); +	return fault; +} + +static fault_t +arm1176jzf_s_mmu_read_halfword (ARMul_State *state, ARMword virt_addr, +			   ARMword *data) +{ +	/* ARMword temp,offset; */ +	fault_t fault; +	fault = arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE); +	return fault; +} + +static fault_t +arm1176jzf_s_mmu_read_word (ARMul_State *state, ARMword virt_addr, ARMword *data) +{ +	return arm1176jzf_s_mmu_read (state, virt_addr, data, ARM_WORD_TYPE); +} + +static fault_t +arm1176jzf_s_mmu_read (ARMul_State *state, ARMword va, ARMword *data, +		  ARMword datatype) +{ +	fault_t fault; +	ARMword pa, real_va, temp, offset; +	ARMword perm;		/* physical addr access permissions */ +	int ap, sop; + +	d_msg ("va = %x\n", va); + +	va = mmu_pid_va_map (va); +	real_va = va; +	/* if MMU disabled, memory_read */ +	if (MMU_Disabled) { +//            printf("MMU disabled cpu_id:%x addr:%x.\n", state->mmu.process_id, va); +//            sleep(1); + +		/* *data = mem_read_word(state, va); */ +		if (datatype == ARM_BYTE_TYPE) +			/* *data = mem_read_byte (state, va); */ +			if(state->space.conf_obj != NULL) +				state->space.read(state->space.conf_obj, va, data, 1); +			else +				mem_read_raw(8, va, data); +		else if (datatype == ARM_HALFWORD_TYPE) +			/* *data = mem_read_halfword (state, va); */ +			if(state->space.conf_obj != NULL) +				state->space.read(state->space.conf_obj, va, data, 2); +			else +				mem_read_raw(16, va, data); +		else if (datatype == ARM_WORD_TYPE) +			/* *data = mem_read_word (state, va); */ +			if(state->space.conf_obj != NULL) +				state->space.read(state->space.conf_obj, va, data, 4); +			else +				mem_read_raw(32, va, data); +		else { +			printf ("SKYEYE:1 arm1176jzf_s_mmu_read error: unknown data type %d\n", datatype); +			skyeye_exit (-1); +		} + +		return 0; +	} +//    printf("MMU enabled.\n"); +//    sleep(1); + +	/* align check */ +	if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || +	    ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { +		d_msg ("align\n"); +		return ALIGNMENT_FAULT; +	} + +	/* va &= ~(WORD_SIZE - 1); */ +	#if 0 +	uint32_t page_base; +	page_base = get_phys_page(state, va); +	if((page_base & 0xFFF) == 0){ +		pa = (page_base << 12) | (va & 0xFFF); +		goto skip_translation; +	} +	#endif +	/*translate va to tlb */ +#if 0 +	fault = mmu_translate (state, va, ARM920T_D_TLB (), &tlb); +#endif +	fault = mmu_translate (state, va, &pa, &ap, &sop); +#if 0 +	if(va ==0xbebb1774 || state->Reg[15] == 0x400ff594){ +                //printf("In %s, current=0x%x. mode is %x, pc=0x%x\n", __FUNCTION__, state->CurrInstr, state->Mode, state->Reg[15]); +                printf("In %s, ap is %d, sop is %d, va=0x%x, pa=0x%x, fault=%d, data=0x%x\n", __FUNCTION__, ap, sop, va, pa, fault, data); +                int i; +                for(i = 0; i < 16; i++) +                        printf("Reg[%d]=0x%x\t", i, state->Reg[i]); +                printf("\n"); +        } +#endif +	if (fault) { +		d_msg ("translate\n"); +		//printf("mmu read fault at %x\n", va); +		//printf("fault is %d\n", fault); +		return fault; +	} +//    printf("va is %x pa is %x\n", va, pa); + +	/* no tlb, only check permission */ +	if (!check_perms(state, ap, 1)) { +		if (sop == 0) { +			return SECTION_PERMISSION_FAULT; +		} else { +			return SUBPAGE_PERMISSION_FAULT; +		} +	} +#if 0 +	/*check access permission */ +	fault = check_access (state, va, tlb, 1); +	if (fault) +		return fault; +#endif + +	//insert_tlb(state, va, pa); +skip_translation: +		/* *data = mem_read_word(state, pa); */ +	if (datatype == ARM_BYTE_TYPE) { +		/* *data = mem_read_byte (state, pa | (real_va & 3)); */ +		if(state->space.conf_obj != NULL) +			state->space.read(state->space.conf_obj, pa | (real_va & 3), data, 1); +		else +			mem_read_raw(8, pa | (real_va & 3), data); +		/* mem_read_raw(32, pa | (real_va & 3), data); */ +	} else if (datatype == ARM_HALFWORD_TYPE) { +		/* *data = mem_read_halfword (state, pa | (real_va & 2)); */ +		if(state->space.conf_obj != NULL) +			state->space.read(state->space.conf_obj, pa | (real_va & 3), data, 2); +		else +			mem_read_raw(16, pa | (real_va & 3), data); +		/* mem_read_raw(32, pa | (real_va & 2), data); */ +	} else if (datatype == ARM_WORD_TYPE) +		/* *data = mem_read_word (state, pa); */ +		if(state->space.conf_obj != NULL)	 +			state->space.read(state->space.conf_obj, pa , data, 4); +		else +			mem_read_raw(32, pa, data); +	else { +		printf ("SKYEYE:2 arm1176jzf_s_mmu_read error: unknown data type %d\n", datatype); +		skyeye_exit (-1); +	} +	if(0 && (va == 0x2869c)){ +            	printf("In %s, pa is %x va=0x%x, value is %x pc %x, instr=0x%x\n", __FUNCTION__, pa, va, *data, state->Reg[15], state->CurrInstr); +	} + +	/* ldrex or ldrexb */ +	if(((state->CurrInstr & 0x0FF000F0) == 0x01900090) || +		((state->CurrInstr & 0x0FF000F0) == 0x01d00090)){ +		int rn = (state->CurrInstr & 0xF0000) >> 16; +		if(state->Reg[rn] == va){ +			add_exclusive_addr(state, pa | (real_va & 3)); +			state->exclusive_access_state = 1; +		} +	} +#if 0 +    if (state->pc == 0xc011a868) { +            printf("pa is %x value is %x size is %x\n", pa, data, datatype); +            printf("icounter is %lld\n", state->NumInstrs); +//            exit(-1); +    } +#endif + +	return 0; +} + + +static fault_t +arm1176jzf_s_mmu_write_byte (ARMul_State *state, ARMword virt_addr, ARMword data) +{ +	return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE); +} + +static fault_t +arm1176jzf_s_mmu_write_halfword (ARMul_State *state, ARMword virt_addr, +			    ARMword data) +{ +	return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE); +} + +static fault_t +arm1176jzf_s_mmu_write_word (ARMul_State *state, ARMword virt_addr, ARMword data) +{ +	return arm1176jzf_s_mmu_write (state, virt_addr, data, ARM_WORD_TYPE); +} + + + +static fault_t +arm1176jzf_s_mmu_write (ARMul_State *state, ARMword va, ARMword data, +		   ARMword datatype) +{ +	int b; +	ARMword pa, real_va; +	ARMword perm;		/* physical addr access permissions */ +	fault_t fault; +	int ap, sop; + +#if 0 +	/8 for sky_printk debugger.*/ +	if (va == 0xffffffff) { +		putchar((char)data); +		return 0; +	} +	if (va == 0xBfffffff) { +		putchar((char)data); +		return 0; +	} +#endif + +	d_msg ("va = %x, val = %x\n", va, data); +	va = mmu_pid_va_map (va); +	real_va = va; + +	if (MMU_Disabled) { +		/* mem_write_word(state, va, data); */ +		if (datatype == ARM_BYTE_TYPE) +			/* mem_write_byte (state, va, data); */ +			if(state->space.conf_obj != NULL) +				state->space.write(state->space.conf_obj, va, &data, 1); +			else +				mem_write_raw(8, va, data); +		else if (datatype == ARM_HALFWORD_TYPE) +			/* mem_write_halfword (state, va, data); */ +			if(state->space.conf_obj != NULL) +				state->space.write(state->space.conf_obj, va, &data, 2); +			else +				mem_write_raw(16, va, data); +		else if (datatype == ARM_WORD_TYPE) +			/* mem_write_word (state, va, data); */ +			if(state->space.conf_obj != NULL) +				state->space.write(state->space.conf_obj, va, &data, 4); +			else +				mem_write_raw(32, va, data); +		else { +			printf ("SKYEYE:1 arm1176jzf_s_mmu_write error: unknown data type %d\n", datatype); +			skyeye_exit (-1); +		} +		goto finished_write; +		//return 0; +	} +	/*align check */ +	/* if ((va & (WORD_SIZE - 1)) && MMU_Aligned){ */ +	if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) || +	    ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned)) { +		d_msg ("align\n"); +		return ALIGNMENT_FAULT; +	} +	va &= ~(WORD_SIZE - 1); +	#if 0 +	uint32_t page_base; +	page_base = get_phys_page(state, va); +	if((page_base & 0xFFF) == 0){ +		pa = (page_base << 12) | (va & 0xFFF); +		goto skip_translation; +	} +	#endif +	/*tlb translate */ +	fault = mmu_translate (state, va, &pa, &ap, &sop); +#if 0 +	if(va ==0xbebb1774 || state->Reg[15] == 0x40102334){ +                //printf("In %s, current=0x%x. mode is %x, pc=0x%x\n", __FUNCTION__, state->CurrInstr, state->Mode, state->Reg[15]); +                printf("In %s, ap is %d, sop is %d, va=0x%x, pa=0x%x, fault=%d, data=0x%x\n", __FUNCTION__, ap, sop, va, pa, fault, data); +                int i; +                for(i = 0; i < 16; i++) +                        printf("Reg[%d]=0x%x\t", i, state->Reg[i]); +                printf("\n"); +        } +#endif +	if (fault) { +		d_msg ("translate\n"); +		//printf("mmu write fault at %x\n", va); +		return fault; +	} +//    printf("va is %x pa is %x\n", va, pa); + +	/* no tlb, only check permission */ +	if (!check_perms(state, ap, 0)) { +		if (sop == 0) { +			return SECTION_PERMISSION_FAULT; +		} else { +			return SUBPAGE_PERMISSION_FAULT; +		} +	} + +#if 0 +	/* tlb check access */ +	fault = check_access (state, va, tlb, 0); +	if (fault) { +		d_msg ("check_access\n"); +		return fault; +	} +#endif +#if 0 +    if (pa <= 0x502860ff && (pa + 1 << datatype) > 0x502860ff) { +            printf("pa is %x value is %x size is %x\n", pa, data, datatype); +    } +#endif +#if 0 +    if (state->pc == 0xc011a878) { +            printf("write pa is %x value is %x size is %x\n", pa, data, datatype); +            printf("icounter is %lld\n", state->NumInstrs); +            exit(-1); +    } +#endif +	//insert_tlb(state, va, pa); +skip_translation: +	/* strex */ +	if(((state->CurrInstr & 0x0FF000F0) == 0x01800090) || +		((state->CurrInstr & 0x0FF000F0) == 0x01c00090)){ +		/* failed , the address is monitord now. */ +		int dest_reg = (state->CurrInstr & 0xF000) >> 12; +		if((exclusive_detect(state, pa | (real_va & 3)) == 0) && (state->exclusive_access_state == 1)){ +			remove_exclusive(state, pa | (real_va & 3)); +			state->Reg[dest_reg] = 0; +			state->exclusive_access_state = 0; +		} +		else{ +			state->Reg[dest_reg] = 1; +			//printf("In %s, try to strex a monitored address 0x%x\n", __FUNCTION__, pa); +			return 0; +		} +	} + +	if (datatype == ARM_BYTE_TYPE) { +		/* mem_write_byte (state, +				(pa | (real_va & 3)), +				data); +		*/ +		if(state->space.conf_obj != NULL) +			state->space.write(state->space.conf_obj, (pa | (real_va & 3)), &data, 1); +		else +			mem_write_raw(8, (pa | (real_va & 3)), data); + +	} else if (datatype == ARM_HALFWORD_TYPE) +		/* mem_write_halfword (state, +				    (pa | +				     (real_va & 2)), +				    data); +		*/ +		if(state->space.conf_obj != NULL) +			state->space.write(state->space.conf_obj, (pa | (real_va & 3)), &data, 2); +		else +			mem_write_raw(16, (pa | (real_va & 3)), data); +	else if (datatype == ARM_WORD_TYPE) +		/* mem_write_word (state, pa, data); */ +		if(state->space.conf_obj != NULL) +			state->space.write(state->space.conf_obj, pa, &data, 4); +		else +			mem_write_raw(32, pa, data); +#if 0 +    if (state->NumInstrs > 236403) { +            printf("write memory\n"); +                printf("pa is %x value is %x size is %x\n", pa, data, datatype); +                printf("icounter is %lld\n", state->NumInstrs); +    } +#endif +finished_write: +#if DIFF_WRITE +	if(state->icounter > state->debug_icounter){ +		if(state->CurrWrite >= 17 ){ +			printf("Wrong write array, 0x%x",  state->CurrWrite); +			exit(-1); +		} +		uint32 record_data = data; +		if(datatype == ARM_BYTE_TYPE) +			record_data &= 0xFF; +		if(datatype == ARM_HALFWORD_TYPE) +			record_data &= 0xFFFF; + +		state->WriteAddr[state->CurrWrite] = pa | (real_va & 3); +		state->WriteData[state->CurrWrite] = record_data; +		state->WritePc[state->CurrWrite] = state->Reg[15]; +		state->CurrWrite++; +		//printf("In %s, pc=0x%x, addr=0x%x, data=0x%x, CFlag=%d\n", __FUNCTION__, state->Reg[15],  pa | (real_va & 3), record_data, state->CFlag); +	} +#endif + +	return 0; +} + +ARMword +arm1176jzf_s_mmu_mrc (ARMul_State *state, ARMword instr, ARMword *value) +{ +	mmu_regnum_t creg = BITS (16, 19) & 0xf; +	int OPC_1 = BITS (21, 23) & 0x7; +	int OPC_2 = BITS (5, 7) & 0x7; +	ARMword data; + +	switch (creg) { +	case MMU_ID: +		if (OPC_2 == 0) { +			data = state->cpu->cpu_val; +		} else if (OPC_2 == 1) { +			/* Cache type: +			 * 000 0110 1 000 101 110 0 10 000 101 110 0 10 +			 * */ +			data = 0x0D172172; +		} +		break; +	case MMU_CONTROL: +		/* +		 * 6:3          read as 1 +		 * 10           read as 0 +		 * 18,16	read as 1 +		 * */ +		data = (state->mmu.control | 0x50078) & 0xFFFFFBFF; +		break; +	case MMU_TRANSLATION_TABLE_BASE: +#if 0 +		data = state->mmu.translation_table_base; +#endif +		switch (OPC_2) { +		case 0: +			data = state->mmu.translation_table_base0; +			break; +		case 1: +			data = state->mmu.translation_table_base1; +			break; +		case 2: +			data = state->mmu.translation_table_ctrl; +			break; +		default: +			printf ("mmu_mrc read UNKNOWN - p15 c2 opcode2 %d\n", OPC_2); +			break; +		} +		break; +	case MMU_DOMAIN_ACCESS_CONTROL: +		data = state->mmu.domain_access_control; +		break; +	case MMU_FAULT_STATUS: +		/* OPC_2 = 0: data FSR value +		 * */ +		if (OPC_2 == 0) +			data = state->mmu.fault_status; +		if (OPC_2 == 1) +			data = state->mmu.fault_statusi; +		break; +	case MMU_FAULT_ADDRESS: +		data = state->mmu.fault_address; +		break; +	case MMU_PID: +		//data = state->mmu.process_id; +		if(OPC_2 == 0) +			data = state->mmu.process_id; +		else if(OPC_2 == 1) +			data = state->mmu.context_id; +		else if(OPC_2 == 3){ +			data = state->mmu.thread_uro_id; +		} +		else{ +			printf ("mmu_mcr read UNKNOWN - reg %d\n", creg); +		} +		//printf("SKYEYE In %s, read pid 0x%x, OPC_2 %d, instr=0x%x\n", __FUNCTION__, data, OPC_2, instr); +		//exit(-1); +		break; +	default: +		printf ("mmu_mrc read UNKNOWN - reg %d\n", creg); +		data = 0; +		break; +	} +/*      printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]); */ +	*value = data; +	return data; +} + + +static ARMword +arm1176jzf_s_mmu_mcr (ARMul_State *state, ARMword instr, ARMword value) +{ +	mmu_regnum_t creg = BITS (16, 19) & 0xf; +	mmu_regnum_t CRm = BITS (0, 3) & 0xf; +	int OPC_1 = BITS (21, 23) & 0x7; +	int OPC_2 = BITS (5, 7) & 0x7; +	if (!strncmp (state->cpu->cpu_arch_name, "armv6", 5)) { +		switch (creg) { +		case MMU_CONTROL: +		/* +		 * 6:3          read as 1 +		 * 10           read as 0 +		 * 18,16	read as 1 +		 * */ +			if(OPC_2 == 0) +				state->mmu.control = (value | 0x50078) & 0xFFFFFBFF; +			else if(OPC_2 == 1) +				state->mmu.auxiliary_control = value; +			else if(OPC_2 == 2) +				state->mmu.coprocessor_access_control = value; +			else +				fprintf(stderr, "In %s, wrong OPC_2 %d\n", __FUNCTION__, OPC_2); +			break; +		case MMU_TRANSLATION_TABLE_BASE: +			switch (OPC_2) { +				/* int i; */ +				case 0: +#if 0 +				/* TTBR0 */ +					if (state->mmu.translation_table_ctrl & 0x7) { +						for (i = 0; i <= state->mmu.translation_table_ctrl; i++) +							state->mmu.translation_table_base0 &= ~(1 << (5 + i)); +					} +#endif +					state->mmu.translation_table_base0 = (value); +					break; +				case 1: +#if 0 +				/* TTBR1 */ +					if (state->mmu.translation_table_ctrl & 0x7) { +						for (i = 0; i <= state->mmu.translation_table_ctrl; i++) +							state->mmu.translation_table_base1 &= 1 << (5 + i); +					} +#endif +					state->mmu.translation_table_base1 = (value); +					break; +				case 2: +				/* TTBC */ +					state->mmu.translation_table_ctrl = value & 0x7; +					break; +				default: +					printf ("mmu_mcr wrote UNKNOWN - cp15 c2 opcode2 %d\n", OPC_2); +					break; +			} +			//printf("SKYEYE In %s, write TLB_BASE 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr); +			//invalidate_all_tlb(state); +			break; +		case MMU_DOMAIN_ACCESS_CONTROL: +		/* printf("mmu_mcr wrote DACR         "); */ +			state->mmu.domain_access_control = value; +			break; + +		case MMU_FAULT_STATUS: +			if (OPC_2 == 0) +				state->mmu.fault_status = value & 0xFF; +			if (OPC_2 == 1) { +				printf("set fault status instr\n"); +			} +			break; +		case MMU_FAULT_ADDRESS: +			state->mmu.fault_address = value; +			break; + +		case MMU_CACHE_OPS: +			break; +		case MMU_TLB_OPS: +			{ +				switch(CRm){ +				case 5: /* ITLB */ +				{ +					switch(OPC_2){ +						case 0: /* invalidate all */ +							//invalidate_all_tlb(state); +							break; +						case 1: /* invalidate by MVA */ +							//invalidate_by_mva(state, value); +							break; +						case 2: /* invalidate by asid */ +							//invalidate_by_asid(state, value); +							break; +						default: +							printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); +							break; +					} +					break; +				} +				case 6: /* DTLB */ +				{ +					switch(OPC_2){ +						case 0: /* invalidate all */ +							//invalidate_all_tlb(state); +							break; +						case 1: /* invalidate by MVA */ +							//invalidate_by_mva(state, value); +							break; +						case 2: /* invalidate by asid */ +							//invalidate_by_asid(state, value); +							break; +						default: +							printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); +							break; +					} +					break; +				} +				case 7: /* Unified TLB */ +				{ +					switch(OPC_2){ +						case 0: /* invalidate all */ +							//invalidate_all_tlb(state); +							break; +						case 1: /* invalidate by MVA */ +							//invalidate_by_mva(state, value); +							break; +						case 2: /* invalidate by asid */ +							//invalidate_by_asid(state, value); +							break; +						default: +							printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); +							break; +					} +					break; +				} + +				default: +					printf ("mmu_mcr wrote UNKNOWN - reg %d, CRm=%d\n", creg, CRm); +					break; +				} +			//printf("SKYEYE In %s, write TLB 0x%x OPC_1=%d, OPC_2=%d , CRm=%d instr=0x%x\n", __FUNCTION__, value, OPC_1, OPC_2, CRm, instr); +			} +			break; +		case MMU_CACHE_LOCKDOWN: +			/* +			 * FIXME: cache lock down*/ +			break; +		case MMU_TLB_LOCKDOWN: +			printf("SKYEYE In %s, write TLB_LOCKDOWN 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr); +			/* FIXME:tlb lock down */ +			break; +		case MMU_PID: +			//printf("SKYEYE In %s, write pid 0x%x OPC_2=%d instr=0x%x\n", __FUNCTION__, value, OPC_2, instr); +			//state->mmu.process_id = value; +			/*0:24 should be zero. */ +			//state->mmu.process_id = value & 0xfe000000; +			if(OPC_2 == 0) +				state->mmu.process_id = value; +			else if(OPC_2 == 1) +				state->mmu.context_id = value; +			else if(OPC_2 == 3){ +				state->mmu.thread_uro_id = value; +			} +			else{ +				printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); +			} +			break; + +		default: +			printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg); +			break; +		} +	} + +	return No_exp; +} + +/* teawater add for arm2x86 2005.06.19------------------------------------------- */ +static int +arm1176jzf_s_mmu_v2p_dbct (ARMul_State *state, ARMword virt_addr, +		      ARMword *phys_addr) +{ +	fault_t fault; +	int ap, sop; + +	ARMword perm;		/* physical addr access permissions */ +	virt_addr = mmu_pid_va_map (virt_addr); +	if (MMU_Enabled) { + +		/*align check */ +		if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned) { +			d_msg ("align\n"); +			return ALIGNMENT_FAULT; +		} else +			virt_addr &= ~(WORD_SIZE - 1); + +		/*translate tlb */ +		fault = mmu_translate (state, virt_addr, phys_addr, &ap, &sop); +		if (fault) { +			d_msg ("translate\n"); +			return fault; +		} + +		/* permission check */ +		if (!check_perms(state, ap, 1)) { +			if (sop == 0) { +				return SECTION_PERMISSION_FAULT; +			} else { +				return SUBPAGE_PERMISSION_FAULT; +			} +		} +#if 0 +		/*check access */ +		fault = check_access (state, virt_addr, tlb, 1); +		if (fault) { +			d_msg ("check_fault\n"); +			return fault; +		} +#endif +	} + +	if (MMU_Disabled) { +		*phys_addr = virt_addr; +	} + +	return 0; +} + +/* AJ2D-------------------------------------------------------------------------- */ + +/*arm1176jzf-s mmu_ops_t*/ +mmu_ops_t arm1176jzf_s_mmu_ops = { +	arm1176jzf_s_mmu_init, +	arm1176jzf_s_mmu_exit, +	arm1176jzf_s_mmu_read_byte, +	arm1176jzf_s_mmu_write_byte, +	arm1176jzf_s_mmu_read_halfword, +	arm1176jzf_s_mmu_write_halfword, +	arm1176jzf_s_mmu_read_word, +	arm1176jzf_s_mmu_write_word, +	arm1176jzf_s_mmu_load_instr, +	arm1176jzf_s_mmu_mcr, +	arm1176jzf_s_mmu_mrc +/* teawater add for arm2x86 2005.06.19------------------------------------------- */ +/*	arm1176jzf_s_mmu_v2p_dbct, */ +/* AJ2D-------------------------------------------------------------------------- */ +}; diff --git a/src/core/src/arm/mmu/arm1176jzf_s_mmu.h b/src/core/src/arm/mmu/arm1176jzf_s_mmu.h new file mode 100644 index 000000000..62097222c --- /dev/null +++ b/src/core/src/arm/mmu/arm1176jzf_s_mmu.h @@ -0,0 +1,37 @@ +/* +    arm1176JZF-S_mmu.h - ARM1176JZF-S Memory Management Unit emulation. + +    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 +*/ + +#ifndef _ARM1176JZF_S_MMU_H_ +#define _ARM1176JZF_S_MMU_H_ + +#if 0 +typedef struct arm1176jzf-s_mmu_s +{ +	tlb_t i_tlb; +	cache_t i_cache; + +	tlb_t d_tlb; +	cache_t d_cache; +	wb_t wb_t; +} arm1176jzf-s_mmu_t; +#endif +extern mmu_ops_t arm1176jzf_s_mmu_ops; + +ARMword +arm1176jzf_s_mmu_mrc (ARMul_State *state, ARMword instr, ARMword *value); +#endif /*_ARM1176JZF_S_MMU_H_*/ diff --git a/src/core/src/arm/mmu/cache.h b/src/core/src/arm/mmu/cache.h new file mode 100644 index 000000000..b26d92693 --- /dev/null +++ b/src/core/src/arm/mmu/cache.h @@ -0,0 +1,168 @@ +#ifndef _MMU_CACHE_H_ +#define _MMU_CACHE_H_ + +typedef struct cache_line_t +{ +	ARMword tag;		/*      cache line align address | +				   bit2: last half dirty +				   bit1: first half dirty +				   bit0: cache valid flag +				 */ +	ARMword pa;		/*physical address */ +	ARMword *data;		/*array of cached data */ +} cache_line_t; +#define TAG_VALID_FLAG 0x00000001 +#define TAG_FIRST_HALF_DIRTY 0x00000002 +#define TAG_LAST_HALF_DIRTY	0x00000004 + +/*cache set association*/ +typedef struct cache_set_s +{ +	cache_line_t *lines; +	int cycle; +} cache_set_t; + +enum +{ +	CACHE_WRITE_BACK, +	CACHE_WRITE_THROUGH, +}; + +typedef struct cache_s +{ +	int width;		/*bytes in a line */ +	int way;		/*way of set asscociate */ +	int set;		/*num of set */ +	int w_mode;		/*write back or write through */ +	//int a_mode;   /*alloc mode: random or round-bin*/ +	cache_set_t *sets; +  /**/} cache_s; + +typedef struct cache_desc_s +{ +	int width; +	int way; +	int set; +	int w_mode; +//      int a_mode; +} cache_desc_t; + + +/*virtual address to cache set index*/ +#define va_cache_set(va, cache_t) \ +	(((va) / (cache_t)->width) & ((cache_t)->set - 1)) +/*virtual address to cahce line aligned*/ +#define va_cache_align(va, cache_t) \ +		((va) & ~((cache_t)->width - 1)) +/*virtaul address to cache line word index*/ +#define va_cache_index(va, cache_t) \ +		(((va) & ((cache_t)->width - 1)) >> WORD_SHT) + +/*see Page 558 in arm manual*/ +/*set/index format value to cache set value*/ +#define index_cache_set(index, cache_t) \ +	(((index) / (cache_t)->width) & ((cache_t)->set - 1)) + +/*************************cache********************/ +/* mmu cache init + * + * @cache_t :cache_t to init + * @width	:cache line width in byte + * @way		:way of each cache set + * @set		:cache set num + * @w_mode	:cache w_mode + * + * $ -1: error + * 	 0: sucess + */ +int +mmu_cache_init (cache_s * cache_t, int width, int way, int set, int w_mode); + +/* free a cache_t's inner data, the ptr self is not freed, + * when needed do like below: + * 		mmu_cache_exit(cache); + * 		free(cache_t); + * + * @cache_t : the cache_t to free + */ +void mmu_cache_exit (cache_s * cache_t); + +/* mmu cache search + * + * @state	:ARMul_State + * @cache_t	:cache_t to search + * @va		:virtual address + * + * $	NULL:	no cache match + * 		cache	:cache matched + * */ +cache_line_t *mmu_cache_search (ARMul_State * state, cache_s * cache_t, +				ARMword va); + +/*  mmu cache search by set/index  + * + * @state	:ARMul_State + * @cache_t	:cache_t to search + * @index       :set/index value.  + * + * $	NULL:	no cache match + * 		cache	:cache matched + * */ + +cache_line_t *mmu_cache_search_by_index (ARMul_State * state, +					 cache_s * cache_t, ARMword index); + +/* mmu cache alloc + * + * @state :ARMul_State + * @cache_t	:cache_t to alloc from + * @va		:virtual address that require cache alloc, need not cache aligned + * @pa		:physical address of va + * + * $	cache_alloced, always alloc OK + */ +cache_line_t *mmu_cache_alloc (ARMul_State * state, cache_s * cache_t, +			       ARMword va, ARMword pa); + +/* mmu_cache_write_back write cache data to memory + * + * @state: + * @cache_t :cache_t of the cache line + * @cache : cache line + */ +void +mmu_cache_write_back (ARMul_State * state, cache_s * cache_t, +		      cache_line_t * cache); + +/* mmu_cache_clean: clean a cache of va in cache_t + * + * @state	:ARMul_State + * @cache_t	:cache_t to clean + * @va		:virtaul address + */ +void mmu_cache_clean (ARMul_State * state, cache_s * cache_t, ARMword va); +void +mmu_cache_clean_by_index (ARMul_State * state, cache_s * cache_t, +			  ARMword index); + +/* mmu_cache_invalidate : invalidate a cache of va + * + * @state	:ARMul_State + * @cache_t	:cache_t to invalid + * @va		:virt_addr to invalid + */ +void +mmu_cache_invalidate (ARMul_State * state, cache_s * cache_t, ARMword va); + +void +mmu_cache_invalidate_by_index (ARMul_State * state, cache_s * cache_t, +			       ARMword index); + +void mmu_cache_invalidate_all (ARMul_State * state, cache_s * cache_t); + +void +mmu_cache_soft_flush (ARMul_State * state, cache_s * cache_t, ARMword pa); + +cache_line_t* mmu_cache_dirty_cache(ARMul_State * state, cache_s * cache_t); + +#endif /*_MMU_CACHE_H_*/ diff --git a/src/core/src/arm/mmu/rb.h b/src/core/src/arm/mmu/rb.h new file mode 100644 index 000000000..b2850eff9 --- /dev/null +++ b/src/core/src/arm/mmu/rb.h @@ -0,0 +1,55 @@ +#ifndef _MMU_RB_H +#define _MMU_RB_H + +enum rb_type_t +{ +	RB_INVALID = 0,		//invalid +	RB_1,			//1     word +	RB_4,			//4 word +	RB_8,			//8 word +}; + +/*bytes of each rb_type*/ +extern ARMword rb_masks[]; + +#define RB_WORD_NUM 8 +typedef struct rb_entry_s +{ +	ARMword data[RB_WORD_NUM];	//array to store data +	ARMword va;		//first word va +	int type;		//rb type +	fault_t fault;		//fault set by rb alloc +} rb_entry_t; + +typedef struct rb_s +{ +	int num; +	rb_entry_t *entrys; +} rb_s; + +/*mmu_rb_init + * @rb_t	:rb_t to init + * @num		:number of entry + * */ +int mmu_rb_init (rb_s * rb_t, int num); + +/*mmu_rb_exit*/ +void mmu_rb_exit (rb_s * rb_t); + + +/*mmu_rb_search + * @rb_t	:rb_t to serach + * @va		:va address to math + * + * $	NULL :not match + * 		NO-NULL: + * */ +rb_entry_t *mmu_rb_search (rb_s * rb_t, ARMword va); + + +void mmu_rb_invalidate_entry (rb_s * rb_t, int i); +void mmu_rb_invalidate_all (rb_s * rb_t); +void mmu_rb_load (ARMul_State * state, rb_s * rb_t, int i_rb, +		  int type, ARMword va); + +#endif /*_MMU_RB_H_*/ diff --git a/src/core/src/arm/mmu/tlb.h b/src/core/src/arm/mmu/tlb.h new file mode 100644 index 000000000..949fcaade --- /dev/null +++ b/src/core/src/arm/mmu/tlb.h @@ -0,0 +1,94 @@ +#ifndef _MMU_TLB_H_ +#define _MMU_TLB_H_ + +typedef enum tlb_mapping_t +{ +	TLB_INVALID = 0, +	TLB_SMALLPAGE = 1, +	TLB_LARGEPAGE = 2, +	TLB_SECTION = 3, +	TLB_ESMALLPAGE = 4, +	TLB_TINYPAGE = 5 +} tlb_mapping_t; + +extern ARMword tlb_masks[]; + +/* Permissions bits in a TLB entry: + * + *		 31         12 11 10  9  8  7  6  5  4  3   2   1   0 + *		+-------------+-----+-----+-----+-----+---+---+-------+ + * Page:|             | ap3 | ap2 | ap1 | ap0 | C | B |       | + *		+-------------+-----+-----+-----+-----+---+---+-------+ + * + *		 31         12 11 10  9              4  3   2   1   0 + *			+-------------+-----+-----------------+---+---+-------+ + * Section:	|             |  AP |                 | C | B |       | + *			+-------------+-----+-----------------+---+---+-------+ + */ + +/* +section: +	section base address	[31:20] +	AP			- table 8-2, page 8-8 +	domain +	C,B + +page: +	page base address	[31:16] or [31:12] +	ap[3:0] +	domain (from L1) +	C,B +*/ + + +typedef struct tlb_entry_t +{ +	ARMword virt_addr; +	ARMword phys_addr; +	ARMword perms; +	ARMword domain; +	tlb_mapping_t mapping; +} tlb_entry_t; + +typedef struct tlb_s +{ +	int num;		/*num of tlb entry */ +	int cycle;		/*current tlb cycle */ +	tlb_entry_t *entrys; +} tlb_s; + + +#define tlb_c_flag(tlb) \ +	((tlb)->perms & 0x8) +#define tlb_b_flag(tlb) \ +	((tlb)->perms & 0x4) + +#define  tlb_va_to_pa(tlb, va) \ +(\ + {\ +	ARMword mask = tlb_masks[tlb->mapping];      \ +	(tlb->phys_addr & mask) | (va & ~mask);\ + }\ +) + +fault_t +check_access (ARMul_State * state, ARMword virt_addr, tlb_entry_t * tlb, +	      int read); + +fault_t +translate (ARMul_State * state, ARMword virt_addr, tlb_s * tlb_t, +	   tlb_entry_t ** tlb); + +int mmu_tlb_init (tlb_s * tlb_t, int num); + +void mmu_tlb_exit (tlb_s * tlb_t); + +void mmu_tlb_invalidate_all (ARMul_State * state, tlb_s * tlb_t); + +void +mmu_tlb_invalidate_entry (ARMul_State * state, tlb_s * tlb_t, ARMword addr); + +tlb_entry_t *mmu_tlb_search (ARMul_State * state, tlb_s * tlb_t, +			     ARMword virt_addr); + +#endif	    /*_MMU_TLB_H_*/ diff --git a/src/core/src/arm/mmu/wb.h b/src/core/src/arm/mmu/wb.h new file mode 100644 index 000000000..1b987afc3 --- /dev/null +++ b/src/core/src/arm/mmu/wb.h @@ -0,0 +1,63 @@ +#ifndef _MMU_WB_H_ +#define _MMU_WB_H_ + +typedef struct wb_entry_s +{ +	ARMword pa;		//phy_addr +	ARMbyte *data;		//data +	int nb;			//number byte to write +} wb_entry_t; + +typedef struct wb_s +{ +	int num;		//number of wb_entry +	int nb;			//number of byte of each entry +	int first;		// +	int last;		// +	int used;		// +	wb_entry_t *entrys; +} wb_s; + +typedef struct wb_desc_s +{ +	int num; +	int nb; +} wb_desc_t; + +/* wb_init + * @wb_t	:wb_t to init + * @num		:num of entrys + * @nw		:num of word of each entry + * + * $	-1:error + * 		 0:ok + * */ +int mmu_wb_init (wb_s * wb_t, int num, int nb); + + +/* wb_exit + * @wb_t :wb_t to exit + * */ +void mmu_wb_exit (wb_s * wb); + + +/* wb_write_bytes :put bytess in Write Buffer + * @state:	ARMul_State + * @wb_t:	write buffer + * @pa:		physical address + * @data:	data ptr + * @n		number of byte to write + * + * Note: write buffer merge is not implemented, can be done late + * */ +void +mmu_wb_write_bytess (ARMul_State * state, wb_s * wb_t, ARMword pa, +		     ARMbyte * data, int n); + + +/* wb_drain_all + * @wb_t wb_t to drain + * */ +void mmu_wb_drain_all (ARMul_State * state, wb_s * wb_t); + +#endif /*_MMU_WB_H_*/ diff --git a/src/core/src/arm/skyeye_defs.h b/src/core/src/arm/skyeye_defs.h new file mode 100644 index 000000000..9c92b5242 --- /dev/null +++ b/src/core/src/arm/skyeye_defs.h @@ -0,0 +1,110 @@ +#ifndef CORE_ARM_SKYEYE_DEFS_H_ +#define CORE_ARM_SKYEYE_DEFS_H_ + +#include "common.h" + +#define MODE32 + +typedef struct +{ +	const char *cpu_arch_name;	/*cpu architecture version name.e.g. armv4t */ +	const char *cpu_name;	/*cpu name. e.g. arm7tdmi or arm720t */ +	u32 cpu_val;	/*CPU value; also call MMU ID or processor id;see +				   ARM Architecture Reference Manual B2-6 */ +	u32 cpu_mask;	/*cpu_val's mask. */ +	u32 cachetype;	/*this cpu has what kind of cache */ +} cpu_config_t; + +typedef struct conf_object_s{ +	char* objname; +	void* obj; +	char* class_name; +}conf_object_t; + +typedef enum{ +	/* No exception */ +	No_exp = 0, +	/* Memory allocation exception */ +	Malloc_exp, +	/* File open exception */ +	File_open_exp, +	/* DLL open exception */ +	Dll_open_exp, +	/* Invalid argument exception */ +	Invarg_exp, +	/* Invalid module exception */ +	Invmod_exp, +	/* wrong format exception for config file parsing */ +	Conf_format_exp, +	/* some reference excess the predefiend range. Such as the index out of array range */ +	Excess_range_exp, +	/* Can not find the desirable result */ +	Not_found_exp, + +	/* Unknown exception */ +	Unknown_exp +}exception_t; + +typedef enum { +	Align = 0, +	UnAlign	 +}align_t; + +typedef enum { +	Little_endian = 0, +	Big_endian +}endian_t; +//typedef int exception_t; + +typedef enum{ +	Phys_addr = 0, +	Virt_addr +}addr_type_t; + +typedef exception_t(*read_byte_t)(conf_object_t* target, u32 addr, void *buf, size_t count); +typedef exception_t(*write_byte_t)(conf_object_t* target, u32 addr, const void *buf, size_t count); + +typedef struct memory_space{ +	conf_object_t* conf_obj; +	read_byte_t read; +	write_byte_t write; +}memory_space_intf; + + +/* + * a running instance for a specific archteciture. + */ +typedef struct generic_arch_s +{ +	char* arch_name; +	void (*init) (void); +	void (*reset) (void); +	void (*step_once) (void); +	void (*set_pc)(u32 addr); +	u32 (*get_pc)(void); +	u32 (*get_step)(void); +	//chy 2004-04-15  +	//int (*ICE_write_byte) (u32 addr, uint8_t v); +	//int (*ICE_read_byte)(u32 addr, uint8_t *pv); +	u32 (*get_regval_by_id)(int id); +	u32 (*get_regnum)(void); +	char* (*get_regname_by_id)(int id); +	exception_t (*set_regval_by_id)(int id, u32 value); +	/* +	 * read a data by virtual address. +	 */ +	exception_t (*mmu_read)(short size, u32 addr, u32 * value); +	/* +	 * write a data by a virtual address. +	 */ +	exception_t (*mmu_write)(short size, u32 addr, u32 value); +	/** +	 * get a signal from external +	 */ +	//exception_t (*signal)(interrupt_signal_t* signal); + +	endian_t endianess; +	align_t alignment; +} generic_arch_t; + +#endif
\ No newline at end of file  | 
