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

📄 dyn_arm_emul.cpp

📁 arm的模拟器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	if (srv_count > 0)	{		pthread_mutex_lock(&pid_mut);		PID_LIST->push_back(pblk);		pthread_cond_signal(&pid_cond);		pthread_mutex_unlock(&pid_mut);		return;	}	unsigned crc, dres, ind;	/* still we need a lock since threads may now start to work after	 * the main one has runs for a while */	pthread_mutex_lock(&pid_mut);	ind = dll_ind++;	pthread_mutex_unlock(&pid_mut);	mem->read_block(temp_buf1, pblk << shiftval, 1 << shiftval);	if ((dres = lookup_dict(temp_buf1, &crc)) != -1u)	{		load_lib(pblk, dres);		return;	}	if (compile_block(temp_buf1, ind))	{		pthread_mutex_lock(&srv_mut);		update_dll_dict(ind, crc);		pthread_mutex_unlock(&srv_mut);		load_lib(pblk, ind);	}}bool dyn_arm_emulator::compile_block(const byte_t *buf, unsigned ind){	char compilestring[1024];	FILE* outfile;	/*create cpps*/	sprintf(compilestring, "%s/Xcompiled_%u.cpp", cache_dir, ind);	outfile = fopen(compilestring, "w");	if(outfile == NULL) {		fprintf(stderr, "Can't open %s to write", compilestring);		exit(1);	}	fprintf(outfile, "#include <arch_jit.hpp>\n");	fprintf(outfile, "#include <dyn_arm_emul.hpp>\n");	if (user_level)		fprintf(outfile, "typedef arm_emulator arm_emul_t;\n");	else		fprintf(outfile, "typedef dyn_arm_emulator arm_emul_t;\n");	decomp_block(outfile, buf, 1 << shiftval, user_level, ind);	fclose(outfile);	sprintf(compilestring, 		CXX MORE_OPTION " %s/Xcompiled_%u.cpp"		" -Wl,-soname,libXcompiled_%u.so"		" -o %s/libXcompiled_%u.so"		" -I%s/include -DSIMIT_COMPILED_ISS %s",		cache_dir, ind, ind, cache_dir, ind, PREFIX,		user_level?"":"-DSIMIT_SYSTEM_LEVEL");	if (showmsg)		fprintf(stderr,"%s\n", compilestring);	if (system(compilestring)==0) {		if (showmsg)			fprintf(stderr,"...done!\n");	}	else {		if (showmsg)			fprintf(stderr,"...failed!\n");		// something is wrong, stop simulation		if (status==ST_RUNNING)			status = ST_ELSE;		return false;	}	sprintf(compilestring,"%s/Xcompiled_%u.dat", cache_dir, ind);	outfile = fopen(compilestring, "wb");	if(outfile == NULL) {		fprintf(stderr, "Can't open %s to write", compilestring);		exit(1);	}	fwrite(buf, 1, 1 << shiftval, outfile);	fclose(outfile);	return true;}char *emitc_default(char *buf,	unsigned curpc, target_inst_t inst, unsigned size){	buf += sprintf(buf, "ABORT2(UndefinedInstrV);\n");	return buf;}static inline uint32_t popcount16(uint32_t x){	x = (x & 0x5555) + ((x >> 1) & 0x5555);	x = (x & 0x3333) + ((x >> 2) & 0x3333);	x = (x & 0x0F0F) + ((x >> 4) & 0x0F0F);	x = (x & 0x00FF) + ((x >> 8) & 0x00FF);	return x;}typedef arm_emulator emulator_t;typedef arm_inst_t target_inst_t;typedef arm_addr_t target_addr_t;#include "auto_emitc.h"#include "arm_gen.hpp"#include "arm_dec.h"#define UFLD ((inst>>23)&1)#define PFLD ((inst>>24)&1)#define WFLD ((inst>>21)&1)#define sIGN ((inst>>6)&1)#define HFLD ((inst>>5)&1)#define LFLD ((inst>>20)&1)static void emit_ldm_hack(char *buf, arm_inst_t inst){	int ii, count;	int pcount = popcount16(inst & 0xFFFF) << 2;	buf += sprintf(buf,		"\tuint32_t base_addr;\n"		"\tuint32_t address;\n"		"\tuint32_t start_addr;\n"		"\tuint32_t val32;\n"		"\tuint32_t cnt;\n"		"\tmmu_fault_t fault;\n");	buf += sprintf(buf, "\tstatic word_t ind[] = {");	for (ii=0, count=0; ii<16; ii++) {		if (inst&(1<<ii)) {			buf += sprintf(buf, "%d, ", ii);		}	}	buf += sprintf(buf, "};\n");	buf += sprintf(buf,		"\tbase_addr = READ_REG(%d);\n", RNFLD);	if (!PFLD && UFLD) {		buf += sprintf(buf,			"\tstart_addr = READ_REG(%d);\n", RNFLD);		if (WFLD)			buf += sprintf(buf,			"\tWRITE_REG(%d, READ_REG(%d) + %d);\n", RNFLD, RNFLD, pcount);	}	else if (PFLD && UFLD) {		buf += sprintf(buf,			"\tstart_addr = READ_REG(%d) + 4;\n", RNFLD);		if (WFLD)			buf += sprintf(buf,			"\tWRITE_REG(%d, READ_REG(%d) + %d);\n", RNFLD, RNFLD, pcount);	}	else if (!PFLD && !UFLD) {		buf += sprintf(buf,			"\tstart_addr = READ_REG(%d) - %d + 4;\n", RNFLD, pcount);		if (WFLD)			buf += sprintf(buf,			"\tWRITE_REG(%d, READ_REG(%d) - %d);\n", RNFLD, RNFLD, pcount); 	}														 	else {															buf += sprintf(buf,			"\tstart_addr = READ_REG(%d) - %d;\n", RNFLD, pcount);		if (WFLD)			buf += sprintf(buf,							   			"\tWRITE_REG(%d, READ_REG(%d) - %d);\n", RNFLD, RNFLD, pcount); 	}															  	//if (BITn(inst, 15) & BITn(inst, 22))					  	//	buf += sprintf(buf, "\tWRITE_CPSR(SPSR);\n");		 															  	/*ignore the last two bits of the address*/			   	buf += sprintf(buf, "\taddress = start_addr & 0xfffffffc;\n");	  	buf += sprintf(buf,	"\tfor (cnt = 0; cnt < %d; cnt++)\n"	"\t{\n"	"\t\tMMU_READ_WORD(address, &val32);\n"	"\t\tif (fault)\n"	"\t\t{\n"	"\t\t\tWRITE_REG(%d, base_addr);\n"	"\t\t\tXSCALE_UPDATE_FSR_FAR(ARMul_CP15_R5_ST_ALIGN, address);\n"	"\t\t\tABORT( DataAbortV );\n"	"\t\t}\n"	"\t\tWRITE_REG(ind[cnt], val32);\n"	"\t\taddress += 4;\n"	"\t}\n", pcount >> 2, RNFLD);}static void emit_stm_hack(char *buf, arm_inst_t inst){	int ii, count;	int pcount = popcount16(inst & 0xFFFF) << 2;	buf += sprintf(buf,		"\tuint32_t base_addr;\n"		"\tuint32_t address;\n"		"\tuint32_t start_addr;\n"		"\tuint32_t val32;\n"		"\tuint32_t cnt;\n"		"\tmmu_fault_t fault;\n");	buf += sprintf(buf, "\tstatic word_t ind[] = {");	for (ii=0, count=0; ii<16; ii++) {		if (inst&(1<<ii)) {			buf += sprintf(buf, "%d, ", ii);		}	}	buf += sprintf(buf, "};\n");	buf += sprintf(buf,		"\tbase_addr = READ_REG(%d);\n", RNFLD);	if (!PFLD && UFLD) {		buf += sprintf(buf,			"\tstart_addr = READ_REG(%d);\n", RNFLD);		if (WFLD)			buf += sprintf(buf,			"\tWRITE_REG(%d, READ_REG(%d) + %d);\n", RNFLD, RNFLD, pcount);	}	else if (PFLD && UFLD) {		buf += sprintf(buf,			"\tstart_addr = READ_REG(%d) + 4;\n", RNFLD);		if (WFLD)			buf += sprintf(buf,			"\tWRITE_REG(%d, READ_REG(%d) + %d);\n", RNFLD, RNFLD, pcount);	}	else if (!PFLD && !UFLD) {		buf += sprintf(buf,			"\tstart_addr = READ_REG(%d) - %d + 4;\n", RNFLD, pcount);		if (WFLD)			buf += sprintf(buf,			"\tWRITE_REG(%d, READ_REG(%d) - %d);\n", RNFLD, RNFLD, pcount); 	}														 	else {		buf += sprintf(buf,			"\tstart_addr = READ_REG(%d) - %d;\n", RNFLD, pcount);		if (WFLD)			buf += sprintf(buf,			"\tWRITE_REG(%d, READ_REG(%d) - %d);\n", RNFLD, RNFLD, pcount); 	}	//if (BITn(inst, 15) & BITn(inst, 22))	//	buf += sprintf(buf, "\tWRITE_CPSR(SPSR);\n");		 															  	/*ignore the last two bits of the address*/	buf += sprintf(buf, "\taddress = start_addr & 0xfffffffc;\n");	  	/* translate the address */	buf += sprintf(buf,	"\tfor (cnt = 0; cnt < %d; cnt++)\n"	"\t{\n"	"\t\tMMU_WRITE_WORD(address, READ_REG(ind[cnt]));\n"	"\t\tif (fault)\n"	"\t\t{\n"	"\t\t\tWRITE_REG(%d, base_addr);\n"	"\t\t\tXSCALE_UPDATE_FSR_FAR(ARMul_CP15_R5_ST_ALIGN, address);\n"	"\t\t\tABORT( DataAbortV );\n"	"\t\t}\n"	"\t\taddress += 4;\n"	"\t}\n", pcount >> 2, RNFLD);}/* return the CRC of the block */void simit::decomp_block(FILE *outfile, const byte_t *pblk,	unsigned size, bool user_level, unsigned ind){	char buf[4096];	/*print preamble of a function*/	fprintf(outfile,	"extern \"C\" void compiled_%u(arm_emul_t *emu, "		"arm_inst_t _start_addr) {\n", ind);#if 0	fprintf(outfile, "\tif (!(_start_addr >= 0x%x && _start_addr < 0x%x)) {\n"			"\t\tfprintf(stderr, \"pc=%%x\\n\", _start_addr);\n\t}\n", 			fstart, fend);	fprintf(outfile, "\tassert(_start_addr >= 0x%x && _start_addr < 0x%x);\n",			fstart, fend);	fprintf(outfile, "#undef CISS_FSTART\n");	fprintf(outfile, "#undef CISS_FEND\n");	fprintf(outfile, "#define CISS_FSTART 0x%x\n", fstart);	fprintf(outfile, "#define CISS_FEND 0x%x\n", fend);#endif	/*define variables*/	fprintf(outfile,		"word_t _virt_blk_ind;\n"		"word_t _lpc;\n");		/*label table*/	fprintf(outfile,		"static void *labels[%u] = {\n\t&&L%x", size/4, 0);	for (target_addr_t kk = 4; kk < size; kk += 4) {		fprintf(outfile, ", &&L%x", kk);		if ((kk)%16==0) fprintf(outfile, "\n\t");	}   	fprintf(outfile, "};\n");	fprintf(outfile, "#define OFFSET_MASK 0x%x\n", (size - 1));	fprintf(outfile, "#define INDEX_MASK 0x%x\n", ~(size - 1));		//fprintf(outfile,	//	"#undef _virt_blk_ind\n"	//	"#define _virt_blk_ind 0x%x\n", fstart);	/*goto start*/	fprintf(outfile,		"_virt_blk_ind = _start_addr & INDEX_MASK;\n"		"_lpc = (_start_addr & OFFSET_MASK) >> 2;\n"		"goto *labels[_lpc];\n");	for (unsigned offset_pc = 0; offset_pc < size; offset_pc+=4 ) {		/*labels*/		fprintf(outfile, "L%x:\n", offset_pc);		target_inst_t inst;		DIRECT_READ_WORD(pblk + offset_pc, inst);		/* if this is nop */		if ((inst << 4) == 0 || inst == 0xe1a00000) 		{#ifdef SINGLESTEP // DEBUG			fprintf(outfile, "  LONG_JUMP(%uU, %uU);\n",					offset_pc, offset_pc+4);			fprintf(outfile, "  return;\n");#endif			continue;		}				fprintf(outfile, "#undef CISS_PC\n");		fprintf(outfile, "#define CISS_PC 0x%x\n", offset_pc);		fprintf(outfile, "#undef CISS_INST\n");		fprintf(outfile, "#define CISS_INST 0x%x\n", inst);		/* deal with ldm1/stm1 only, for now */		if ((inst & 0xE400000) == 0x08000000) {			if (BITn(inst, 20))				emit_ldm_hack(buf, inst);			else				emit_stm_hack(buf, inst);		}		else			emit_code(buf, offset_pc, inst, size);		/* predicates */		switch (COND) {			case 0: //EQ				fprintf(outfile, "  if (Z_FLAG) {\n");				break;			case 1:	//NE				fprintf(outfile, "  if (!Z_FLAG) {\n");				break;			case 2: //CS				fprintf(outfile, "  if (C_FLAG) {\n");				break;			case 3: //CC				fprintf(outfile, "  if (!C_FLAG) {\n");				break;			case 4: //MI				fprintf(outfile, "  if (N_FLAG) {\n");				break;			case 5: //PL				fprintf(outfile, "  if (!N_FLAG) {\n");				break;			case 6: //VS				fprintf(outfile, "  if (V_FLAG) {\n");				break;			case 7: //VC				fprintf(outfile, "  if (!V_FLAG) {\n");				break;			case 8: //HI				fprintf(outfile, "  if (C_FLAG & !Z_FLAG) {\n");				break;			case 9: //LS				fprintf(outfile, "  if (!C_FLAG | Z_FLAG) {\n");				break;			case 10: //GE				fprintf(outfile, "  if (N_FLAG==V_FLAG) {\n");				break;			case 11: //LT				fprintf(outfile, "  if (N_FLAG!=V_FLAG) {\n");				break;			case 12: //GT				fprintf(outfile, "  if (!(Z_FLAG | (N_FLAG^V_FLAG))) {\n");				break;			case 13: //LE				fprintf(outfile, "  if (Z_FLAG | (N_FLAG^V_FLAG)) {\n");				break;			case 14: //AL				fprintf(outfile, "  {\n");				break;			case 15: //NV			default:				break;		}		if (COND!=15) {			fprintf(outfile, "%s", buf);			fprintf(outfile, "  }\n");		}#ifdef SINGLESTEP // DEBUG		fprintf(outfile, "  LONG_JUMP(%uU, %uU);\n", offset_pc, offset_pc+4);		fprintf(outfile, "  return;\n");#endif		/* end of instruction */	}	/* print the tail of a function 	   print CISS_PC again in case the last instruction is a nop	*/	fprintf(outfile, "#undef CISS_PC\n");	fprintf(outfile, "#define CISS_PC 0x%x\n", size-4);	fprintf(outfile, "LONG_JUMP(%uU, %uU);\n}\n", size-4, size);}bool dyn_arm_emulator::ld_lib(unsigned ind){	char ldstring[1024];	sprintf(ldstring,		CXX MORE_OPTION " %s/Xcompiled_%u.o"		" -o %s/libXcompiled_%u.so",		cache_dir, ind, cache_dir, ind);	if (showmsg)		fprintf(stderr, "%s\n", ldstring);	if (system(ldstring)==0) {		if (showmsg)			fprintf(stderr, "...done!\n");		return true;	}	if (showmsg)		fprintf(stderr, "...failed!\n");	return false;}bool dyn_arm_emulator::read_or_create_dll_dict(){	char l1dir[1024];	char l2dir[1024];	bool ret = false;	strcpy(l1dir, getenv("HOME"));	strcat(l1dir, "/.ema/");	if (!access(l1dir, W_OK) || !mkdir(l1dir, 0770))	{		sprintf(l2dir, "%s%c%d/", l1dir,			user_level?'u':'s', 1 << (shiftval - 2));		if (!access(l2dir, W_OK) || !mkdir(l2dir, 0770))		{			cache_dir = strdup(l2dir);			ret = true;		}	}	if (ret)	{		sprintf(l2dir, "%s/dict.dat", cache_dir);		if (!access(l2dir, R_OK | W_OK))		{			read_dll_dict();		}		else		{			int fd = creat(l2dir, 0660);			if (fd==-1)				ret = false;			else				close(fd);		}	}		if (!ret)		fprintf(stderr,			"Cannot create dictionary to insufficient permission!\n");	return ret;}void dyn_arm_emulator::read_dll_dict(){	FILE* datin;	char fullpath[1024];	unsigned val1, val2;	/* clear the dictionary */	DLL_DICT->clear();	sprintf(fullpath,"%s/dict.dat",cache_dir);	datin = fopen(fullpath, "r");	if(datin == NULL)	{		fprintf(stderr, "Can't open dictionary at %s to read", fullpath);		return;	}	/* lines contain dll_index crc */	while(fscanf(datin, "%u %u", &val1, &val2) != EOF)	{		DLL_DICT->insert(pair<unsigned, unsigned>(val1, val2));		if (val2 >= dll_ind) dll_ind = val2 + 1; 	}	fclose(datin);}void dyn_arm_emulator::update_dll_dict(unsigned ind, unsigned crc){	FILE *outfile;	/*addr backup data*/	char fullpath[1024];	sprintf(fullpath,"%s/dict.dat",cache_dir);	outfile = fopen(fullpath, "a");	if(outfile == NULL)	{		fprintf(stderr, "Can't open dictionary at %s to append", fullpath);		return;	}	fprintf(outfile, "%u %u\n", crc, ind); 	fclose(outfile);}bool dyn_arm_emulator::load_lib(unsigned pblk, unsigned ind){	char* error;	char filename[1024];	char funname[1024];

⌨️ 快捷键说明

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