📄 risc_x86.h
字号:
case DOP_MOV: cache_addb(0xb8+(gr1->index)); dr1->flags|=DYNFLG_CHANGED; goto finish; default: IllegalOption("gen_dop_word_imm"); } dr1->flags|=DYNFLG_CHANGED;nochange: cache_addw(tmp+(gr1->index<<8));finish: if (dword) cache_addd(imm); else cache_addw(imm);}static void gen_dop_word_imm_mem(DualOps op,bool dword,DynReg * dr1,void* data) { GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV); Bit16u tmp; switch (op) { case DOP_ADD: tmp=0x0503; break; case DOP_ADC: tmp=0x0513; break; case DOP_SUB: tmp=0x052b; break; case DOP_SBB: tmp=0x051b; break; case DOP_CMP: tmp=0x053b; goto nochange; //Doesn't change case DOP_XOR: tmp=0x0533; break; case DOP_AND: tmp=0x0523; break; case DOP_OR: tmp=0x050b; break; case DOP_TEST: tmp=0x0585; goto nochange; //Doesn't change case DOP_MOV: gen_mov_host(data,dr1,dword?4:2); dr1->flags|=DYNFLG_CHANGED; return; default: IllegalOption("gen_dop_word_imm_mem"); } dr1->flags|=DYNFLG_CHANGED;nochange: if (!dword) cache_addb(0x66); cache_addw(tmp+(gr1->index<<11)); cache_addd((Bit32u)data);}static void gen_dop_word_var(DualOps op,bool dword,DynReg * dr1,void* drd) { GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV); Bit8u tmp; switch (op) { case DOP_ADD: tmp=0x03; break; case DOP_ADC: tmp=0x13; break; case DOP_SUB: tmp=0x2b; break; case DOP_SBB: tmp=0x1b; break; case DOP_CMP: tmp=0x3b; break; case DOP_XOR: tmp=0x33; break; case DOP_AND: tmp=0x23; break; case DOP_OR: tmp=0x0b; break; case DOP_TEST: tmp=0x85; break; case DOP_MOV: tmp=0x8b; break; case DOP_XCHG: tmp=0x87; break; default: IllegalOption("gen_dop_word_var"); } if (!dword) cache_addb(0x66); cache_addw(tmp|(0x05+((gr1->index)<<3))<<8); cache_addd((Bit32u)drd);}static void gen_imul_word(bool dword,DynReg * dr1,DynReg * dr2) { GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2); dr1->flags|=DYNFLG_CHANGED; if (!dword) { cache_addd(0xaf0f66|(0xc0+(gr1->index<<3)+gr2->index)<<24); } else { cache_addw(0xaf0f); cache_addb(0xc0+(gr1->index<<3)+gr2->index); }}static void gen_imul_word_imm(bool dword,DynReg * dr1,DynReg * dr2,Bits imm) { GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2); if (!dword) cache_addb(0x66); if ((imm>=-128 && imm<=127)) { cache_addb(0x6b); cache_addb(0xc0+(gr1->index<<3)+gr2->index); cache_addb(imm); } else { cache_addb(0x69); cache_addb(0xc0+(gr1->index<<3)+gr2->index); if (dword) cache_addd(imm); else cache_addw(imm); } dr1->flags|=DYNFLG_CHANGED;}static void gen_sop_word(SingleOps op,bool dword,DynReg * dr1) { GenReg * gr1=FindDynReg(dr1); if (!dword) cache_addb(0x66); switch (op) { case SOP_INC:cache_addb(0x40+gr1->index);break; case SOP_DEC:cache_addb(0x48+gr1->index);break; case SOP_NOT:cache_addw(0xd0f7+(gr1->index<<8));break; case SOP_NEG:cache_addw(0xd8f7+(gr1->index<<8));break; default: IllegalOption("gen_sop_word"); } dr1->flags|=DYNFLG_CHANGED;}static void gen_shift_byte_cl(Bitu op,DynReg * dr1,Bit8u di1,DynReg * drecx) { ForceDynReg(x86gen.regs[X86_REG_ECX],drecx); GenReg * gr1=FindDynReg(dr1); cache_addw(0xc0d2+(((Bit16u)op) << 11)+ ((gr1->index+di1)<<8)); dr1->flags|=DYNFLG_CHANGED;}static void gen_shift_byte_imm(Bitu op,DynReg * dr1,Bit8u di1,Bit8u imm) { GenReg * gr1=FindDynReg(dr1); cache_addw(0xc0c0+(((Bit16u)op) << 11) + ((gr1->index+di1)<<8)); cache_addb(imm); dr1->flags|=DYNFLG_CHANGED;}static void gen_shift_word_cl(Bitu op,bool dword,DynReg * dr1,DynReg * drecx) { ForceDynReg(x86gen.regs[X86_REG_ECX],drecx); GenReg * gr1=FindDynReg(dr1); if (!dword) cache_addb(0x66); cache_addw(0xc0d3+(((Bit16u)op) << 11) + ((gr1->index)<<8)); dr1->flags|=DYNFLG_CHANGED;}static void gen_shift_word_imm(Bitu op,bool dword,DynReg * dr1,Bit8u imm) { GenReg * gr1=FindDynReg(dr1); dr1->flags|=DYNFLG_CHANGED; if (!dword) { cache_addd(0x66|((0xc0c1+((Bit16u)op << 11) + (gr1->index<<8))|imm<<16)<<8); } else { cache_addw(0xc0c1+((Bit16u)op << 11) + (gr1->index<<8)); cache_addb(imm); }}static void gen_cbw(bool dword,DynReg * dyn_ax) { ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); if (!dword) cache_addb(0x66); cache_addb(0x98); dyn_ax->flags|=DYNFLG_CHANGED;}static void gen_cwd(bool dword,DynReg * dyn_ax,DynReg * dyn_dx) { ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); ForceDynReg(x86gen.regs[X86_REG_EDX],dyn_dx); dyn_ax->flags|=DYNFLG_CHANGED; dyn_dx->flags|=DYNFLG_CHANGED; if (!dword) cache_addw(0x9966); else cache_addb(0x99);}static void gen_mul_byte(bool imul,DynReg * dyn_ax,DynReg * dr1,Bit8u di1) { ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); GenReg * gr1=FindDynReg(dr1); if (imul) cache_addw(0xe8f6+((gr1->index+di1)<<8)); else cache_addw(0xe0f6+((gr1->index+di1)<<8)); dyn_ax->flags|=DYNFLG_CHANGED;}static void gen_mul_word(bool imul,DynReg * dyn_ax,DynReg * dyn_dx,bool dword,DynReg * dr1) { ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); ForceDynReg(x86gen.regs[X86_REG_EDX],dyn_dx); GenReg * gr1=FindDynReg(dr1); if (!dword) cache_addb(0x66); if (imul) cache_addw(0xe8f7+(gr1->index<<8)); else cache_addw(0xe0f7+(gr1->index<<8)); dyn_ax->flags|=DYNFLG_CHANGED; dyn_dx->flags|=DYNFLG_CHANGED;}static void gen_dshift_imm(bool dword,bool left,DynReg * dr1,DynReg * dr2,Bitu imm) { GenReg * gr1=FindDynReg(dr1); GenReg * gr2=FindDynReg(dr2); if (!dword) cache_addb(0x66); if (left) cache_addw(0xa40f); //SHLD IMM else cache_addw(0xac0f); //SHRD IMM cache_addb(0xc0+gr1->index+(gr2->index<<3)); cache_addb(imm); dr1->flags|=DYNFLG_CHANGED;}static void gen_dshift_cl(bool dword,bool left,DynReg * dr1,DynReg * dr2,DynReg * drecx) { ForceDynReg(x86gen.regs[X86_REG_ECX],drecx); GenReg * gr1=FindDynReg(dr1); GenReg * gr2=FindDynReg(dr2); if (!dword) cache_addb(0x66); if (left) cache_addw(0xa50f); //SHLD CL else cache_addw(0xad0f); //SHRD CL cache_addb(0xc0+gr1->index+(gr2->index<<3)); dr1->flags|=DYNFLG_CHANGED;}static void gen_call_function(void * func,char * ops,...) { Bits paramcount=0; bool release_flags=false; struct ParamInfo { char * line; Bitu value; } pinfo[32]; ParamInfo * retparam=0; /* Clear the EAX Genreg for usage */ x86gen.regs[X86_REG_EAX]->Clear(); x86gen.regs[X86_REG_EAX]->notusable=true; /* Save the flags */ if (GCC_UNLIKELY(!skip_flags)) gen_protectflags(); /* Scan for the amount of params */ if (ops) { va_list params; va_start(params,ops); Bitu stack_used=0; bool free_flags=false; Bits pindex=0; while (*ops) { if (*ops=='%') { pinfo[pindex].line=ops+1; pinfo[pindex].value=va_arg(params,Bitu);#if defined (MACOSX) char * scan=pinfo[pindex].line; if ((*scan=='I') || (*scan=='D')) stack_used+=4; else if (*scan=='F') free_flags=true;#endif pindex++; } ops++; }#if defined (MACOSX) /* align stack */ stack_used+=4; // saving esp on stack as well cache_addw(0xc48b); // mov eax,esp cache_addb(0x2d); // sub eax,stack_used cache_addd(stack_used); cache_addw(0xe083); // and eax,0xfffffff0 cache_addb(0xf0); cache_addb(0x05); // sub eax,stack_used cache_addd(stack_used); cache_addb(0x94); // xchg eax,esp if (free_flags) { cache_addw(0xc083); // add eax,4 cache_addb(0x04); } cache_addb(0x50); // push eax (==old esp)#endif paramcount=0; while (pindex) { pindex--; char * scan=pinfo[pindex].line; switch (*scan++) { case 'I': /* immediate value */ paramcount++; cache_addb(0x68); //Push immediate cache_addd(pinfo[pindex].value); //Push value break; case 'D': /* Dynamic register */ { bool release=false; paramcount++; DynReg * dynreg=(DynReg *)pinfo[pindex].value; GenReg * genreg=FindDynReg(dynreg); scanagain: switch (*scan++) { case 'd': cache_addb(0x50+genreg->index); //Push reg break; case 'w': cache_addw(0xb70f); //MOVZX EAX,reg cache_addb(0xc0+genreg->index); cache_addb(0x50); //Push EAX break; case 'l': cache_addw(0xb60f); //MOVZX EAX,reg[0] cache_addb(0xc0+genreg->index); cache_addb(0x50); //Push EAX break; case 'h': cache_addw(0xb60f); //MOVZX EAX,reg[1] cache_addb(0xc4+genreg->index); cache_addb(0x50); //Push EAX break; case 'r': /* release the reg afterwards */ release=true; goto scanagain; default: IllegalOption("gen_call_function param:DREG"); } if (release) gen_releasereg(dynreg); } break; case 'R': /* Dynamic register to get the return value */ retparam =&pinfo[pindex]; pinfo[pindex].line=scan; break; case 'F': /* Release flags from stack */ release_flags=true; break; default: IllegalOption("gen_call_function unknown param"); } }#if defined (MACOSX) if (free_flags) release_flags=false; } else { /* align stack */ Bit32u stack_used=8; // saving esp and return address on the stack cache_addw(0xc48b); // mov eax,esp cache_addb(0x2d); // sub eax,stack_used cache_addd(stack_used); cache_addw(0xe083); // and eax,0xfffffff0 cache_addb(0xf0); cache_addb(0x05); // sub eax,stack_used cache_addd(stack_used); cache_addb(0x94); // xchg eax,esp cache_addb(0x50); // push esp (==old esp)#endif } /* Clear some unprotected registers */ x86gen.regs[X86_REG_ECX]->Clear(); x86gen.regs[X86_REG_EDX]->Clear(); /* Do the actual call to the procedure */ cache_addb(0xe8); cache_addd((Bit32u)func - (Bit32u)cache.pos-4); /* Restore the params of the stack */ if (paramcount) { cache_addw(0xc483); //add ESP,imm byte cache_addb(paramcount*4+(release_flags?4:0)); } else if (release_flags) { cache_addw(0xc483); //add ESP,imm byte cache_addb(4); } /* Save the return value in correct register */ if (retparam) { DynReg * dynreg=(DynReg *)retparam->value; GenReg * genreg=FindDynReg(dynreg); if (genreg->index) // test for (e)ax/al switch (*retparam->line) { case 'd': cache_addw(0xc08b+(genreg->index <<(8+3))); //mov reg,eax break; case 'w': cache_addb(0x66); cache_addw(0xc08b+(genreg->index <<(8+3))); //mov reg,eax break; case 'l': cache_addw(0xc08a+(genreg->index <<(8+3))); //mov reg,eax break; case 'h': cache_addw(0xc08a+((genreg->index+4) <<(8+3))); //mov reg,eax break; } dynreg->flags|=DYNFLG_CHANGED; } /* Restore EAX registers to be used again */ x86gen.regs[X86_REG_EAX]->notusable=false;#if defined (MACOSX) /* restore stack */ cache_addb(0x5c); // pop esp#endif}static void gen_call_write(DynReg * dr,Bit32u val,Bitu write_size) { /* Clear the EAX Genreg for usage */ x86gen.regs[X86_REG_EAX]->Clear(); x86gen.regs[X86_REG_EAX]->notusable=true; gen_protectflags();#if defined (MACOSX) /* align stack */ Bitu stack_used=12; cache_addw(0xc48b); // mov eax,esp cache_addb(0x2d); // sub eax,stack_used cache_addd(stack_used); cache_addw(0xe083); // and eax,0xfffffff0 cache_addb(0xf0); cache_addb(0x05); // sub eax,stack_used cache_addd(stack_used); cache_addb(0x94); // xchg eax,esp cache_addb(0x50); // push eax (==old esp)#endif cache_addb(0x68); //PUSH val cache_addd(val); GenReg * genreg=FindDynReg(dr); cache_addb(0x50+genreg->index); //PUSH reg /* Clear some unprotected registers */ x86gen.regs[X86_REG_ECX]->Clear(); x86gen.regs[X86_REG_EDX]->Clear(); /* Do the actual call to the procedure */ cache_addb(0xe8); switch (write_size) { case 1: cache_addd((Bit32u)mem_writeb_checked_x86 - (Bit32u)cache.pos-4); break; case 2: cache_addd((Bit32u)mem_writew_checked_x86 - (Bit32u)cache.pos-4); break; case 4: cache_addd((Bit32u)mem_writed_checked_x86 - (Bit32u)cache.pos-4); break; default: IllegalOption("gen_call_write"); } cache_addw(0xc483); //ADD ESP,8 cache_addb(2*4); x86gen.regs[X86_REG_EAX]->notusable=false; gen_releasereg(dr);#if defined (MACOSX) /* restore stack */ cache_addb(0x5c); // pop esp#endif}static Bit8u * gen_create_branch(BranchTypes type) { /* First free all registers */ cache_addw(0x70+type); return (cache.pos-1);}static void gen_fill_branch(Bit8u * data,Bit8u * from=cache.pos) {#if C_DEBUG Bits len=from-data; if (len<0) len=-len; if (len>126) LOG_MSG("Big jump %d",len);#endif *data=(from-data-1);}static Bit8u * gen_create_branch_long(BranchTypes type) { cache_addw(0x800f+(type<<8)); cache_addd(0); return (cache.pos-4);}static void gen_fill_branch_long(Bit8u * data,Bit8u * from=cache.pos) { *(Bit32u*)data=(from-data-4);}static Bit8u * gen_create_jump(Bit8u * to=0) { /* First free all registers */ cache_addb(0xe9); cache_addd(to-(cache.pos+4)); return (cache.pos-4);}static void gen_fill_jump(Bit8u * data,Bit8u * to=cache.pos) { *(Bit32u*)data=(to-data-4);}static void gen_jmp_ptr(void * ptr,Bits imm=0) { cache_addb(0xa1); cache_addd((Bit32u)ptr); cache_addb(0xff); //JMP EA if (!imm) { //NO EBP cache_addb(0x20); } else if ((imm>=-128 && imm<=127)) { cache_addb(0x60); cache_addb(imm); } else { cache_addb(0xa0); cache_addd(imm); }}static void gen_save_flags(DynReg * dynreg) { if (GCC_UNLIKELY(x86gen.flagsactive)) IllegalOption("gen_save_flags"); GenReg * genreg=FindDynReg(dynreg); cache_addb(0x8b); //MOV REG,[esp] cache_addw(0x2404+(genreg->index << 3)); dynreg->flags|=DYNFLG_CHANGED;}static void gen_load_flags(DynReg * dynreg) { if (GCC_UNLIKELY(x86gen.flagsactive)) IllegalOption("gen_load_flags"); cache_addw(0xc483); //ADD ESP,4 cache_addb(0x4); GenReg * genreg=FindDynReg(dynreg); cache_addb(0x50+genreg->index); //PUSH 32}static void gen_save_host_direct(void * data,Bits imm) { cache_addw(0x05c7); //MOV [],dword cache_addd((Bit32u)data); cache_addd(imm);}static void gen_return(BlockReturn retcode) { gen_protectflags(); cache_addb(0x59); //POP ECX, the flags if (retcode==0) cache_addw(0xc033); //MOV EAX, 0 else { cache_addb(0xb8); //MOV EAX, retcode cache_addd(retcode); } cache_addb(0xc3); //RET}static void gen_return_fast(BlockReturn retcode,bool ret_exception=false) { if (GCC_UNLIKELY(x86gen.flagsactive)) IllegalOption("gen_return_fast"); cache_addw(0x0d8b); //MOV ECX, the flags cache_addd((Bit32u)&cpu_regs.flags); if (!ret_exception) { cache_addw(0xc483); //ADD ESP,4 cache_addb(0x4); if (retcode==0) cache_addw(0xc033); //MOV EAX, 0 else { cache_addb(0xb8); //MOV EAX, retcode cache_addd(retcode); } } cache_addb(0xc3); //RET}static void gen_init(void) { x86gen.regs[X86_REG_EAX]=new GenReg(0); x86gen.regs[X86_REG_ECX]=new GenReg(1); x86gen.regs[X86_REG_EDX]=new GenReg(2); x86gen.regs[X86_REG_EBX]=new GenReg(3); x86gen.regs[X86_REG_EBP]=new GenReg(5); x86gen.regs[X86_REG_ESI]=new GenReg(6); x86gen.regs[X86_REG_EDI]=new GenReg(7);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -