📄 dyn_arm_emul.cpp
字号:
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 + -