📄 hdefs.c
字号:
return n;}static UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem ){ return toUChar( ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7) );}static UChar mkSIB ( Int shift, Int regindex, Int regbase ){ return toUChar( ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7) );}static UChar* emit32 ( UChar* p, UInt w32 ){ *p++ = toUChar( w32 & 0x000000FF); *p++ = toUChar((w32 >> 8) & 0x000000FF); *p++ = toUChar((w32 >> 16) & 0x000000FF); *p++ = toUChar((w32 >> 24) & 0x000000FF); return p;}/* Does a sign-extend of the lowest 8 bits give the original number? */static Bool fits8bits ( UInt w32 ){ Int i32 = (Int)w32; return toBool(i32 == ((i32 << 24) >> 24));}/* Forming mod-reg-rm bytes and scale-index-base bytes. greg, 0(ereg) | ereg != ESP && ereg != EBP = 00 greg ereg greg, d8(ereg) | ereg != ESP = 01 greg ereg, d8 greg, d32(ereg) | ereg != ESP = 10 greg ereg, d32 greg, d8(%esp) = 01 greg 100, 0x24, d8 ----------------------------------------------- greg, d8(base,index,scale) | index != ESP = 01 greg 100, scale index base, d8 greg, d32(base,index,scale) | index != ESP = 10 greg 100, scale index base, d32*/static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am ) { if (am->tag == Xam_IR) { if (am->Xam.IR.imm == 0 && am->Xam.IR.reg != hregX86_ESP() && am->Xam.IR.reg != hregX86_EBP() ) { *p++ = mkModRegRM(0, iregNo(greg), iregNo(am->Xam.IR.reg)); return p; } if (fits8bits(am->Xam.IR.imm) && am->Xam.IR.reg != hregX86_ESP()) { *p++ = mkModRegRM(1, iregNo(greg), iregNo(am->Xam.IR.reg)); *p++ = toUChar(am->Xam.IR.imm & 0xFF); return p; } if (am->Xam.IR.reg != hregX86_ESP()) { *p++ = mkModRegRM(2, iregNo(greg), iregNo(am->Xam.IR.reg)); p = emit32(p, am->Xam.IR.imm); return p; } if (am->Xam.IR.reg == hregX86_ESP() && fits8bits(am->Xam.IR.imm)) { *p++ = mkModRegRM(1, iregNo(greg), 4); *p++ = 0x24; *p++ = toUChar(am->Xam.IR.imm & 0xFF); return p; } ppX86AMode(am); vpanic("doAMode_M: can't emit amode IR"); /*NOTREACHED*/ } if (am->tag == Xam_IRRS) { if (fits8bits(am->Xam.IRRS.imm) && am->Xam.IRRS.index != hregX86_ESP()) { *p++ = mkModRegRM(1, iregNo(greg), 4); *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index, am->Xam.IRRS.base); *p++ = toUChar(am->Xam.IRRS.imm & 0xFF); return p; } if (am->Xam.IRRS.index != hregX86_ESP()) { *p++ = mkModRegRM(2, iregNo(greg), 4); *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index, am->Xam.IRRS.base); p = emit32(p, am->Xam.IRRS.imm); return p; } ppX86AMode(am); vpanic("doAMode_M: can't emit amode IRRS"); /*NOTREACHED*/ } vpanic("doAMode_M: unknown amode"); /*NOTREACHED*/}/* Emit a mod-reg-rm byte when the rm bit denotes a reg. */static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg ) { *p++ = mkModRegRM(3, iregNo(greg), iregNo(ereg)); return p;}/* Emit ffree %st(7) */static UChar* do_ffree_st7 ( UChar* p ){ *p++ = 0xDD; *p++ = 0xC7; return p;}/* Emit fstp %st(i), 1 <= i <= 7 */static UChar* do_fstp_st ( UChar* p, Int i ){ vassert(1 <= i && i <= 7); *p++ = 0xDD; *p++ = toUChar(0xD8+i); return p;}/* Emit fld %st(i), 0 <= i <= 6 */static UChar* do_fld_st ( UChar* p, Int i ){ vassert(0 <= i && i <= 6); *p++ = 0xD9; *p++ = toUChar(0xC0+i); return p;}/* Emit f<op> %st(0) */static UChar* do_fop1_st ( UChar* p, X86FpOp op ){ switch (op) { case Xfp_NEG: *p++ = 0xD9; *p++ = 0xE0; break; case Xfp_ABS: *p++ = 0xD9; *p++ = 0xE1; break; case Xfp_SQRT: *p++ = 0xD9; *p++ = 0xFA; break; case Xfp_ROUND: *p++ = 0xD9; *p++ = 0xFC; break; case Xfp_SIN: *p++ = 0xD9; *p++ = 0xFE; break; case Xfp_COS: *p++ = 0xD9; *p++ = 0xFF; break; case Xfp_2XM1: *p++ = 0xD9; *p++ = 0xF0; break; case Xfp_MOV: break; case Xfp_TAN: p = do_ffree_st7(p); /* since fptan pushes 1.0 */ *p++ = 0xD9; *p++ = 0xF2; /* fptan */ *p++ = 0xD9; *p++ = 0xF7; /* fincstp */ break; default: vpanic("do_fop1_st: unknown op"); } return p;}/* Emit f<op> %st(i), 1 <= i <= 5 */static UChar* do_fop2_st ( UChar* p, X86FpOp op, Int i ){# define fake(_n) mkHReg((_n), HRcInt32, False) Int subopc; switch (op) { case Xfp_ADD: subopc = 0; break; case Xfp_SUB: subopc = 4; break; case Xfp_MUL: subopc = 1; break; case Xfp_DIV: subopc = 6; break; default: vpanic("do_fop2_st: unknown op"); } *p++ = 0xD8; p = doAMode_R(p, fake(subopc), fake(i)); return p;# undef fake}/* Push a 32-bit word on the stack. The word depends on tags[3:0];each byte is either 0x00 or 0xFF depending on the corresponding bit in tags[].*/static UChar* push_word_from_tags ( UChar* p, UShort tags ){ UInt w; vassert(0 == (tags & ~0xF)); if (tags == 0) { /* pushl $0x00000000 */ *p++ = 0x6A; *p++ = 0x00; } else /* pushl $0xFFFFFFFF */ if (tags == 0xF) { *p++ = 0x6A; *p++ = 0xFF; } else { vassert(0); /* awaiting test case */ w = 0; if (tags & 1) w |= 0x000000FF; if (tags & 2) w |= 0x0000FF00; if (tags & 4) w |= 0x00FF0000; if (tags & 8) w |= 0xFF000000; *p++ = 0x68; p = emit32(p, w); } return p;}/* Emit an instruction into buf and return the number of bytes used. Note that buf is not the insn's final place, and therefore it is imperative to emit position-independent code. */Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ){ UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc; UInt xtra; UChar* p = &buf[0]; UChar* ptmp; vassert(nbuf >= 32); /* Wrap an integer as a int register, for use assembling GrpN insns, in which the greg field is used as a sub-opcode and does not really contain a register. */# define fake(_n) mkHReg((_n), HRcInt32, False) /* vex_printf("asm ");ppX86Instr(i); vex_printf("\n"); */ switch (i->tag) { case Xin_Alu32R: /* Deal specially with MOV */ if (i->Xin.Alu32R.op == Xalu_MOV) { switch (i->Xin.Alu32R.src->tag) { case Xrmi_Imm: *p++ = toUChar(0xB8 + iregNo(i->Xin.Alu32R.dst)); p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32); goto done; case Xrmi_Reg: *p++ = 0x89; p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg, i->Xin.Alu32R.dst); goto done; case Xrmi_Mem: *p++ = 0x8B; p = doAMode_M(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.src->Xrmi.Mem.am); goto done; default: goto bad; } } /* MUL */ if (i->Xin.Alu32R.op == Xalu_MUL) { switch (i->Xin.Alu32R.src->tag) { case Xrmi_Reg: *p++ = 0x0F; *p++ = 0xAF; p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.src->Xrmi.Reg.reg); goto done; case Xrmi_Mem: *p++ = 0x0F; *p++ = 0xAF; p = doAMode_M(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.src->Xrmi.Mem.am); goto done; case Xrmi_Imm: if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) { *p++ = 0x6B; p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.dst); *p++ = toUChar(0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32); } else { *p++ = 0x69; p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.dst); p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32); } goto done; default: goto bad; } } /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP */ opc = opc_rr = subopc_imm = opc_imma = 0; switch (i->Xin.Alu32R.op) { case Xalu_ADC: opc = 0x13; opc_rr = 0x11; subopc_imm = 2; opc_imma = 0x15; break; case Xalu_ADD: opc = 0x03; opc_rr = 0x01; subopc_imm = 0; opc_imma = 0x05; break; case Xalu_SUB: opc = 0x2B; opc_rr = 0x29; subopc_imm = 5; opc_imma = 0x2D; break; case Xalu_SBB: opc = 0x1B; opc_rr = 0x19; subopc_imm = 3; opc_imma = 0x1D; break; case Xalu_AND: opc = 0x23; opc_rr = 0x21; subopc_imm = 4; opc_imma = 0x25; break; case Xalu_XOR: opc = 0x33; opc_rr = 0x31; subopc_imm = 6; opc_imma = 0x35; break; case Xalu_OR: opc = 0x0B; opc_rr = 0x09; subopc_imm = 1; opc_imma = 0x0D; break; case Xalu_CMP: opc = 0x3B; opc_rr = 0x39; subopc_imm = 7; opc_imma = 0x3D; break; default: goto bad; } switch (i->Xin.Alu32R.src->tag) { case Xrmi_Imm: if (i->Xin.Alu32R.dst == hregX86_EAX() && !fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) { *p++ = toUChar(opc_imma); p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32); } else if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) { *p++ = 0x83; p = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst); *p++ = toUChar(0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32); } else { *p++ = 0x81; p = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst); p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32); } goto done; case Xrmi_Reg: *p++ = toUChar(opc_rr); p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg, i->Xin.Alu32R.dst); goto done; case Xrmi_Mem: *p++ = toUChar(opc); p = doAMode_M(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.src->Xrmi.Mem.am); goto done; default: goto bad; } break; case Xin_Alu32M: /* Deal specially with MOV */ if (i->Xin.Alu32M.op == Xalu_MOV) { switch (i->Xin.Alu32M.src->tag) { case Xri_Reg: *p++ = 0x89; p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg, i->Xin.Alu32M.dst); goto done; case Xri_Imm: *p++ = 0xC7; p = doAMode_M(p, fake(0), i->Xin.Alu32M.dst); p = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32); goto done; default: goto bad; } } /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP. MUL is not allowed here. */ opc = subopc_imm = opc_imma = 0; switch (i->Xin.Alu32M.op) { case Xalu_ADD: opc = 0x01; subopc_imm = 0; break; case Xalu_SUB: opc = 0x29; subopc_imm = 5; break; default: goto bad; } switch (i->Xin.Alu32M.src->tag) { case Xri_Reg: *p++ = toUChar(opc); p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg, i->Xin.Alu32M.dst); goto done; case Xri_Imm: if (fits8bits(i->Xin.Alu32M.src->Xri.Imm.imm32)) { *p++ = 0x83; p = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst); *p++ = toUChar(0xFF & i->Xin.Alu32M.src->Xri.Imm.imm32); goto done; } else { *p++ = 0x81; p = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst); p = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32); goto done; } default: goto bad; } break; case Xin_Sh32: opc_cl = opc_imm = subopc = 0; switch (i->Xin.Sh32.op) { case Xsh_SHR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 5; break; case Xsh_SAR: opc_cl =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -