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

📄 armemul.h

📁 這是一個arm模擬器 以C++實做 主要模擬ARM9架構
💻 H
字号:
/*************************************************************************    Copyright (C) 2002 - 2007 Wei Qin    See file COPYING for more information.    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.*************************************************************************/#ifndef SIMIT_ARMEMUL_H#define SIMIT_ARMEMUL_H#include <cstdio>#include <misc.h> // search follows the path of -I's#include "emumem.h"namespace simit{/* some types for the arm architecture */typedef enum{	SA1100 = 0x4401a100,	PXA250 = 0x69052100,	PXA270 = 0x69054110,} cpu_id_t;typedef enum{	USR_MODE = 16L,	FIQ_MODE = 17L,	IRQ_MODE = 18L,	SVC_MODE = 19L,	ABT_MODE = 23L,	UND_MODE = 27L,	SYS_MODE = 31L,} cpu_mode_t;typedef enum{	USR_BANK = 0,	FIQ_BANK = 1,	IRQ_BANK = 2,	SVC_BANK = 3,	ABT_BANK = 4,	UND_BANK = 5,	DUM_BANK = 6,	SYS_BANK = USR_BANK,} reg_bank_t;typedef enum{	ResetV          = 0L,	UndefinedInstrV = 4L,	SWIV            = 8L,	PrefetchAbortV  = 12L,	DataAbortV      = 16L,	AddrExceptnV    = 20L,	IRQV            = 24L,	FIQV            = 28L,} ex_vector_t;const word_t ABORTWORD = 0xefffffff;   /* SWI -1 *//* forward declaration of some member classes */class arm_mmu;class arm_io;	class arm_copro;class arm_emulator {  public:	/* constructor */	arm_emulator(bool verbose, bool user_level);	/* destructor */	~arm_emulator();	/* reset everything */	void reset();	/* if verbose flag set */	bool is_verbose() const {return verbose;}	/* if syscall need to be emulated */	bool is_user_level() const {return user_level;}	/* load an ELF user-level program, set up stack/heap/mmap */	void load_program(const char *, int argc, char *argv[], char *env[]);	/* load an ELF OS image, no need to set up stack/heap */	void load_osimage(const char *);	/* load a binary image to address */	void load_binary(const char *, arm_addr_t);	/* load a configuration file that sets up cpu and memory */	bool load_config(const char *);	/* get the cpu_id value */	cpu_id_t get_cpu_id() const {return cpu_val;}	/* if this is xscale */	bool is_xscale() const {return cpu_val==PXA250 || cpu_val==PXA270;}	/* run the program till exit*/	uint64_t run();	/* debug a program */	void debug();	/* user interruption, can be called from CTRL-C handler */	void interrupt();	bool is_interrupted() const {return status==ST_SIGINT;}	/* brk instruction */	void break_point();	bool is_broken() const {return status==ST_BREAK;}	/* error */	void seg_fault();	bool is_fault() const {return status==ST_ERROR;}	/* check status */	bool is_running()   const {return status==ST_RUNNING;}	bool is_debugging() const {return status==ST_DEBUGGING;}	void set_running()  {status=ST_RUNNING;}	/* program exit, used in user-level simulation */	void prog_exit(int);	bool is_done() const {return status==ST_EXIT;}	/* get the exit code of the program, used in user-level simulation */	int get_retcode() const {return retcode;}	/* if pc is set by the loader or the configuration file */	bool is_pc_set() const {return pc_set;}	/******************************************************************	   cpu mode	 *****************************************************************/	/* switch mode and change bank, return the old mode */	cpu_mode_t switch_cpu_mode(cpu_mode_t new_mode)	{		switch_reg_bank(mode, new_mode);		return translation_mode(new_mode);	}	/* get the mode */	cpu_mode_t get_cpu_mode() const {return mode;}	/* check if in one exception mode */	bool is_exception_mode () const {return mode_exception;}	/* check if in one privilege mode */	bool is_privilege_mode () const {return mode_privilege;}	/* switch the mode, returns the old mode, but does not change reg bank */	cpu_mode_t translation_mode(cpu_mode_t new_mode);	/* change register bank, and returns the old mode */	void switch_reg_bank(cpu_mode_t old_mode, cpu_mode_t new_mode);	/* raise an exception, vector is the address to jump to */	void raise_exception (ex_vector_t vector);	/******************************************************************	   register access interfaces 	 *****************************************************************/	word_t get_pc() const {return my_regs.gpr[PC_REAL_IND];}	word_t read_gpr(int index) const {return my_regs.gpr[index];}	void write_gpr(int index, word_t val)	{		my_regs.gpr[index==15?PC_REAL_IND:index] = val;	}	void write_gpr2(int index, word_t val)	{		my_regs.gpr[index] = val;	}	word_t read_cpsr() const	{		return my_regs.cpsr&0xfffffff | (my_regs.cc&0xf)<<28;	}	void write_cpsr(word_t val)	{		if (mode != (cpu_mode_t)(val&0x1f)){			switch_cpu_mode((cpu_mode_t)(val&0x1f));		}		my_regs.cpsr=val;		my_regs.cc=(val>>28)&0xf;		my_regs.i_flag = (val>>7)& 1;		my_regs.f_flag = (val>>6)& 1;	}	word_t read_spsr() const	{		if (bank) //not User Bank = has spsr = Exception Mode 			return my_regs.spsr[bank];/*----add processor mode and bank----*/		else			return read_cpsr();	}	void write_spsr(word_t val)	{		if (bank)//not User Bank = has spsr = Exception Mode			my_regs.spsr[bank]=val;/*----------------add processor mode------ */	}	word_t read_cc() const {return my_regs.cc;}	void write_cc(word_t val) {my_regs.cc=val;}	/* some convenience routine for interpretation */	void update_CPSR(word_t val, word_t mask);	void update_SPSR(word_t val, word_t mask);	/******************************************************************	   The CC access functions below are for compiled simulators  	 *****************************************************************/	word_t read_NZF() const {return my_regs.NZF;}	word_t read_CF() const {return my_regs.CF;}	word_t read_VF() const {return my_regs.VF;}	void write_NZF(word_t val) {my_regs.NZF = val;}	void write_CF(word_t val) {my_regs.CF = val;}	void write_VF(word_t val) {my_regs.VF = val;}	/* conversion from one set of NZCV to the other set */	void cfs_to_cc()	{		my_regs.cc = ((my_regs.NZF>>28)&8) | (my_regs.CF<<1) |					 ((my_regs.NZF==0)<<2) | (my_regs.VF>>31);	}	void cc_to_cfs()	{		my_regs.NZF = ((my_regs.cc&4)^4) | ((my_regs.cc&8)<<28);		my_regs.CF = (my_regs.cc>>1)&1;		my_regs.VF = (my_regs.cc)<<31;	}	/******************************************************************	   The counter access functions	 *****************************************************************/	/* total instruction counter, compiled counter */	uint64_t get_icount() const {return icount;}	uint64_t get_ccount() const {return ccount;}    /* instruction counters, used by the compiled simulator */    void increment_compile_count(uint32_t val) {ccount += val;}    void increment_interpret_count(uint32_t val) {icount += val;} 	/* stats output */	void dump_instruction_counters(FILE *);	/* stats initialization */	void reset_instruction_counters();	/* decrement the prescale counter */	void decrement_pcount(int c) {pcount -= c;}	/* set the maximum instructions to simulate, default is -1 */	void set_max_count(uint64_t mcount) {max_count = mcount;}	/* memory */	memory *mem;	/* mmu */	arm_mmu	*mmu;	/******************************************************************	   The signal functions	 *****************************************************************/	void raise_reset_signal() {NresetSig = false; SigSet = true;}	void raise_fiq_signal()   {NfiqSig = false;   SigSet = true;}	void raise_irq_signal()   {NirqSig = false;   SigSet = true;}	void clear_reset_signal() {NresetSig = true; SigSet = !(NfiqSig & NirqSig);}	void clear_fiq_signal()   {NfiqSig = true; SigSet = !(NresetSig & NirqSig);}	void clear_irq_signal()   {NirqSig = true; SigSet = !(NresetSig & NfiqSig);}  protected:	/* reset the content of the registers */	void init_registers();	/* fetch an instruction in system level*/	arm_inst_t fetch_inst_system(arm_addr_t addr);	/* fetch an instruction in user level */	arm_inst_t fetch_inst_user(arm_addr_t addr) 	{		word_t inst;		mem->read_word(addr, &inst);		return inst;	}	/* execute one instruction in system level*/	void execute_system(arm_inst_t inst, word_t addr);	/* execute one instruction in user level */	void execute_user(arm_inst_t inst, word_t addr);	/* fetch and run one instruction in system level */	void step_system();	/* fetch and run one instruction in user level */	void step_user();	/* run in system level */	uint64_t run_system();	/* run in user level */	uint64_t run_user();	uint64_t run_user_count();	/* debug routines */	void debug_trace(int count);	void debug_go_to(arm_addr_t addr);	void debug_dump_registers(FILE *stream);	void debug_disasm(FILE *stream, arm_addr_t addr);	void debug_dump(FILE *stream, arm_addr_t addr);	/* convert mode to bank */	reg_bank_t mode_to_bank(cpu_mode_t m) const;	/* prescale counter for periodical IO update */	int pcount;	/******************************************************************	   icount -- total instruction counter,	   ccount -- compiled counter, only used in compiled simulation mode	 *****************************************************************/	uint64_t icount, ccount;	bool max_count_set;	uint64_t max_count;	/* registers */	struct regs_t {		word_t gpr[NUM_GPR];		word_t cpsr;		word_t spsr[7];				/* extra copy of NCZV flags, used to accelerate interpretation */		word_t cc;		/* another copy of NCZV flags, used to accelerate compiled ISS */		word_t NZF; // the actual result, bit 31 is N		word_t CF;	// bit 0 is the carry		word_t VF;	// bit 31 is overflow		/* extra copy of cpsr bits, used to accelerate interpretation */		word_t i_flag; // bit 7 of cpsr: Disables IRQ interrupts when set		word_t f_flag; // bit 6 of cpsr: Disables FIQ interrupts when set			/* Big member stays in the back so that the compiled can use		*  small offsets for all previous members. Small offsets reduce		*  code size on x86.		*/		word_t reg_bank[7][16];	} my_regs;	bool NresetSig;	/* reset the processor */	bool NfiqSig;	bool NirqSig;	bool SigSet;	/* a signal is set, !NresetSig | !NfigSig | !NirqSig*/	/******************************************************************       miscellaneous simulation status	 *****************************************************************/	int retcode;	// valid on ST_EXIT	enum status_t 	{		ST_RESET,		// just reset, empty		ST_IDLE,		// program loaded		ST_RUNNING,		ST_DEBUGGING,		ST_ERROR,		// memory protection violation		ST_EXIT,		// program exit normally		ST_SIGINT,		// user interrupted		ST_BREAK,		// brk instruction		ST_ELSE,	} status;	reg_bank_t bank;	cpu_mode_t mode;	bool   mode_exception;	bool   mode_privilege;	/******************************************************************       configuration parameters	 *****************************************************************/	const bool verbose;	const bool user_level;	const int  prescale;	cpu_id_t cpu_val;	/******************************************************************	   some loader related functions and variables	 *****************************************************************/	void load_elf32(const char *);	bool cpu_config(const char *);	// some variables for the ELF loader	uint32_t data_base;	uint32_t data_size;	uint32_t prog_base;	// variable for configuration file, pc set in configuration file	bool pc_set;  public:	/******************************************************************	   some less frequently used members 	 *****************************************************************/	/* io */	arm_io  *io;	/* coprocessors */	arm_copro *copro[16];	/******************************************************************	   finally some system call emulation related stuff, user-level only	 *****************************************************************/	arm_addr_t syscall_get_brk() const {return brk_point;}	arm_addr_t syscall_get_mmap_brk() const {return mmap_brk_point;}	/* set brk point for syscall emulation, mmap is actually not used */	void syscall_set_brk(arm_addr_t addr) {brk_point = addr;}	void syscall_set_mmap_brk(arm_addr_t addr) {mmap_brk_point = addr;}	void syscall_alloc_buf(unsigned size);	void syscall_realloc_buf(unsigned size);	/* some variables for system call states */    int syscall_phase;    int syscall_iret;    void *syscall_buf;	unsigned syscall_mem_size;    int syscall_open_len;    int syscall_open_addr;    int syscall_times_ret;  private:	target_addr_t brk_point;	target_addr_t mmap_brk_point;  public:	word_t val_register[16]; /*Validation Suite Coprocessor's Registers*/	uint64_t accumulator;   /*Xscale coprocessor0 acc0 */		bool int_pending(void);	/* This returns the number of clock ticks since the last reset.  */	uint64_t time(void) const {return icount + ccount;}	unsigned abort_addr; /* For Prefetch Abort */  };} /* namespace */#endif

⌨️ 快捷键说明

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