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

📄 armemul.cpp

📁 arm的模拟器
💻 CPP
字号:
/*************************************************************************    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.*************************************************************************/#include <csignal>#include <cstdio>#include <cassert>#include <cstdlib>#include <cstring>#include "armemul.h"#include "armmmu.h"#include "arm_io.h" #include "sa_io.h" #include "pxa_io.h" #include "armcopro.h" #include "decode.h"using namespace simit;typedef arm_emulator emulator_t;typedef arm_inst_t target_inst_t;typedef arm_addr_t target_addr_t;static const uint16_t cond_table[] ={0xf0f0, 0x0f0f, 0xcccc, 0x3333, 0xff00, 0x00ff, 0xaaaa, 0x5555, 0x0c0c, 0xf3f3, 0xaa55, 0x55aa, 0x0a05, 0xf5fa, 0xffff, 0x0000};static inline uint32_t eval_cond(arm_emulator *emu, arm_inst_t inst){	uint32_t val;	val = (cond_table[COND] >> CC) & 1;#if 0	switch (COND) {		case 0: val = Z_FLAG; break;		case 1: val = !Z_FLAG; break;		case 2: val = C_FLAG; break;		case 3: val = !C_FLAG; break;		case 4: val = N_FLAG; break;		case 5: val = !N_FLAG; break;		case 6: val = V_FLAG; break;		case 7: val = !V_FLAG; break;		case 8: val = C_FLAG & ~Z_FLAG; break;		case 9: val = !(C_FLAG & ~Z_FLAG); break;		case 10: val = N_FLAG == V_FLAG; break;		case 11: val = N_FLAG ^ V_FLAG; break;		case 12: val = !(Z_FLAG | (N_FLAG ^ V_FLAG)); break;		case 13: val = Z_FLAG | (N_FLAG ^ V_FLAG); break;		case 14: val = 1; break;		default: val = 0; break;	}#endif	return val;}arm_emulator::arm_emulator(bool verbose, bool user_level) :	verbose(verbose), user_level(user_level), prescale(IO_DIVISOR){	mem = new memory(0);	mmu = new arm_mmu(this);	for(int ii=1; ii<16; ii++) copro[ii] = NULL;	io = NULL;	syscall_buf = NULL;	reset();	pc_set = false;	max_count_set = false;	max_count = (uint64_t)-1;}arm_emulator::~arm_emulator(){	delete mem;	delete mmu;	delete io;	for(int ii=1; ii<16; ii++) delete copro[ii];	if (syscall_buf) {		free(syscall_buf);	}	}void arm_emulator::reset(){	mem->reset();	clear_reset_signal();	clear_irq_signal();	clear_fiq_signal();	for(int ii=1; ii<16; ii++) val_register[ii] = 0;	init_registers();	reset_instruction_counters();	status = ST_RESET;		abort_addr = 1;	if (syscall_buf) {		free(syscall_buf);		syscall_buf = NULL;	}}bool arm_emulator::cpu_config(const char *cpu_name){//	copro[1] =	new copro1(this);//	copro[2] =	new copro2(this);//	copro[4] =	new copro4(this);//	copro[5] =	new copro5(this);	copro[15]=	new copro15(this);	//mmu	if (strcasecmp(cpu_name, "SA1100") == 0)	{ 		io		 =	new sa_io(this);		cpu_val  =	SA1100;		my_regs.gpr[1] = 109;	/*adsbitsy machine id. */	}	else if (strncasecmp(cpu_name, "PXA25", 5) == 0)	{		copro[14]=	new copro14(this);		io		 =	new pxa_io(this);		cpu_val =	PXA250;		my_regs.gpr[1] = 89;    /*lubbock machine id.*/		mmu->set_xscale();	}	else if	(strncasecmp(cpu_name, "PXA27", 5) == 0) 	{		copro[6] =	new copro6(this);		copro[14]=	new copro14(this);		io		 =	new pxa_io(this);		cpu_val = PXA270;		my_regs.gpr[1] = 406;	/*mainstone machine id. */		mmu->set_xscale();	}	else{ 		return false;	}	return true;}void arm_emulator::prog_exit(int ret){	status = ST_EXIT;	retcode = ret;}void arm_emulator::interrupt(){	if (status==ST_RUNNING || status==ST_DEBUGGING)		status = ST_SIGINT;	else		exit(0);}void arm_emulator::break_point(){	if (status==ST_RUNNING || status==ST_DEBUGGING)		status = ST_BREAK;}void arm_emulator::seg_fault(){	status = ST_ERROR;	retcode = 1;}/* Two sets of interpretation routines,   one performs system-level simulation, one does user-level.   The difference is the macros in arch.hpp.*/#define  SIMIT_SYSTEM_LEVEL#include "auto_impl.h"#include "arm_iss.hpp"#include "arm_dec.h"void arm_emulator::execute_system(arm_inst_t inst, word_t addr){#if 0	arm_disassemble_to_stream(inst, get_pc(), stderr);	fprintf(stderr, "0x%08x : 0x%08x\n", addr, inst);#endif	/* set default next PC; operation can override */	write_gpr2(PC_REAL_IND, addr+4);	if (COND == 0xe || eval_cond(this, inst)) {		/*operation sees PC+8*/		write_gpr2(PC_AHEAD_IND, addr+8);		decode_main_system(this, inst);	}}#undef   SIMIT_SYSTEM_LEVEL#include "auto_impl.h"#include "arm_iss.hpp"#include "arm_dec.h"void arm_emulator::execute_user(arm_inst_t inst, word_t addr){#if 0	arm_disassemble_to_stream(inst, get_pc(), stderr);	fprintf(stderr, "0x%08x : 0x%08x\n", addr, inst);#endif	/* set default next PC; operation can override */	write_gpr2(PC_REAL_IND, addr+4);	if (COND == 0xe || eval_cond(this, inst)) {		/*operation sees PC+8*/		write_gpr2(PC_AHEAD_IND, addr+8);		decode_main_user(this, inst);	}}arm_inst_t arm_emulator::fetch_inst_system(arm_addr_t addr){	mmu_fault_t fault;	word_t inst;		fault =  mmu->load_instr(addr, &inst);	if (fault){		abort_addr = addr ;		return ABORTWORD;	}	return inst;}void arm_emulator::step_system(){	arm_inst_t inst;	if (SigSet) {		/* Any exceptions ?  */		if (!NresetSig) {			raise_exception (ResetV);			return;		}		else if ((!NfiqSig) && (!my_regs.f_flag)) {			raise_exception (FIQV);			return;		}		else if ((!NirqSig) && (!my_regs.i_flag)) {			raise_exception (IRQV);			return;		}	}	if(pcount <= 0){		io->do_cycle();		icount += prescale - pcount;		pcount = prescale;		if (max_count_set && icount >= max_count)			status = ST_EXIT;	}	pcount--;	inst = fetch_inst_system(get_pc()); 	execute_system(inst, get_pc());}void arm_emulator::step_user(){	arm_inst_t inst;	inst = fetch_inst_user(get_pc());	execute_user(inst, get_pc());	icount++;}uint64_t arm_emulator::run_user(){	icount = 0;	status = ST_RUNNING;	while(status==ST_RUNNING)		step_user();	return icount;}uint64_t arm_emulator::run_user_count(){	icount = 0;	status = ST_RUNNING;	while(status==ST_RUNNING && icount < max_count)		step_user();	return icount;}uint64_t arm_emulator::run_system(){	icount = 0;	status = ST_RUNNING;	pcount = prescale;	while(status==ST_RUNNING)		step_system();	icount += prescale - pcount;	return icount;}uint64_t arm_emulator::run(){	max_count_set = (max_count != (uint64_t)-1);	if (user_level)		return max_count_set?run_user_count():run_user();	else 		return run_system();}void arm_emulator::init_registers(){	int ii, jj;	for (ii = 0; ii < NUM_GPR; ii++)		my_regs.gpr[ii] = 0;		for (ii = 0; ii < 7; ii++)		for (jj = 0; jj < 16; jj++)			my_regs.reg_bank[ii][jj] = 0;		mode = SVC_MODE;	mode_exception = true;	mode_privilege = true;	bank = SVC_BANK;	my_regs.cpsr = 0xc0 | mode; //skyeye INTBITS	my_regs.spsr[bank] = 0;	my_regs.cc = 0;	my_regs.i_flag = 1;	my_regs.f_flag = 1;}	/* switch the mode, returns the old mode, but does not change reg bank */cpu_mode_t arm_emulator::translation_mode(cpu_mode_t new_mode){	cpu_mode_t old_mode = mode;	mode = new_mode;	/* mode_exception as a cache for fast checking */	mode_exception = ((mode != USR_MODE) && (mode != SYS_MODE));	mode_privilege = (mode != USR_MODE);		/*switch all pages' access permision */	mmu->evaluate_access_all();	return old_mode;}void arm_emulator::reset_instruction_counters(){	icount = 0;	ccount = 0;}void arm_emulator::dump_instruction_counters(FILE *fp){	fputs("Total instructions : ", fp);	dump_int64(icount+ccount, fp);	if (icount+ccount > 1000000) {		fputs(" (", fp);		dump_int64_smart(icount+ccount, fp);		fputs(")", fp);	}	/* in the compiled simulator */	if (ccount) {		fprintf(fp, ", including %.2lf%% compiled",			100.0*ccount/(icount+ccount));	}	fputs("\n", fp);}void arm_emulator::syscall_realloc_buf(unsigned size){	assert(syscall_buf!=NULL);	syscall_buf = realloc(syscall_buf, size);	if (syscall_buf==NULL) {        fprintf(stderr, "Error: Out of host memory when allocating %d"            " bytes for a system call.\n", size);        exit(-1);	}}void arm_emulator::syscall_alloc_buf(unsigned size){	if (syscall_buf!=NULL)		free(syscall_buf);	syscall_buf = malloc(size);	if (syscall_buf==NULL) {        fprintf(stderr, "Error: Out of host memory when reallocating %d"            " bytes for a system call.\n", size);        exit(-1);	}}void arm_emulator::update_CPSR(word_t val, word_t mask){    uint32_t result;    result = read_cpsr();    if (!user_level && mode != USR_MODE)	{        if (mask&1)			result = (result & 0xFFFFFF00) | (val & 0x000000FF);				if (mask&2)			result = (result & 0xFFFF00FF) | (val & 0x0000FF00);				if (mask&4)			result = (result & 0xFF00FFFF) | (val & 0x00FF0000);    }	if (mask&8)		result = (result & 0x00FFFFFF) | (val & 0xFF000000);    write_cpsr(result);}void arm_emulator::update_SPSR(word_t val, word_t mask){    uint32_t result;    if (!user_level && mode_exception) 	{    	result = read_spsr();        if (mask&1)			result = (result & 0xFFFFFF00) | (val & 0x000000FF);				if (mask&2)			result = (result & 0xFFFF00FF) | (val & 0x0000FF00);				if (mask&4)			result = (result & 0xFF00FFFF) | (val & 0x00FF0000);				if (mask&8)			result = (result & 0x00FFFFFF) | (val & 0xFF000000);		write_spsr(result);    }} 

⌨️ 快捷键说明

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