x86_emulate.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,781 行 · 第 1/5 页
C
1,781 行
if ( segr.attr.fields.g ) segr.limit = (segr.limit << 12) | 0xfffu; segr.sel = sel; return ops->write_segment(seg, &segr, ctxt); raise_exn: if ( ops->inject_hw_exception == NULL ) return X86EMUL_UNHANDLEABLE; if ( (rc = ops->inject_hw_exception(fault_type, sel & 0xfffc, ctxt)) ) return rc; return X86EMUL_EXCEPTION;}static intload_seg( enum x86_segment seg, uint16_t sel, struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops){ if ( (ops->read_segment == NULL) || (ops->write_segment == NULL) ) return X86EMUL_UNHANDLEABLE; if ( in_protmode(ctxt, ops) ) return protmode_load_seg(seg, sel, ctxt, ops); return realmode_load_seg(seg, sel, ctxt, ops);}void *decode_register( uint8_t modrm_reg, struct cpu_user_regs *regs, int highbyte_regs){ void *p; switch ( modrm_reg ) { case 0: p = ®s->eax; break; case 1: p = ®s->ecx; break; case 2: p = ®s->edx; break; case 3: p = ®s->ebx; break; case 4: p = (highbyte_regs ? ((unsigned char *)®s->eax + 1) : (unsigned char *)®s->esp); break; case 5: p = (highbyte_regs ? ((unsigned char *)®s->ecx + 1) : (unsigned char *)®s->ebp); break; case 6: p = (highbyte_regs ? ((unsigned char *)®s->edx + 1) : (unsigned char *)®s->esi); break; case 7: p = (highbyte_regs ? ((unsigned char *)®s->ebx + 1) : (unsigned char *)®s->edi); break;#if defined(__x86_64__) case 8: p = ®s->r8; break; case 9: p = ®s->r9; break; case 10: p = ®s->r10; break; case 11: p = ®s->r11; break; case 12: p = ®s->r12; break; case 13: p = ®s->r13; break; case 14: p = ®s->r14; break; case 15: p = ®s->r15; break;#endif default: p = NULL; break; } return p;}#define decode_segment_failed x86_seg_trenum x86_segmentdecode_segment( uint8_t modrm_reg){ switch ( modrm_reg ) { case 0: return x86_seg_es; case 1: return x86_seg_cs; case 2: return x86_seg_ss; case 3: return x86_seg_ds; case 4: return x86_seg_fs; case 5: return x86_seg_gs; default: break; } return decode_segment_failed;}intx86_emulate( struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops){ /* Shadow copy of register state. Committed on successful emulation. */ struct cpu_user_regs _regs = *ctxt->regs; uint8_t b, d, sib, sib_index, sib_base, twobyte = 0, rex_prefix = 0; uint8_t modrm = 0, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; unsigned int op_bytes, def_op_bytes, ad_bytes, def_ad_bytes;#define REPE_PREFIX 1#define REPNE_PREFIX 2 unsigned int lock_prefix = 0, rep_prefix = 0; int override_seg = -1, rc = X86EMUL_OKAY; struct operand src, dst; /* Data operand effective address (usually computed from ModRM). */ struct operand ea; /* Default is a memory operand relative to segment DS. */ ea.type = OP_MEM; ea.mem.seg = x86_seg_ds; ea.mem.off = 0; ctxt->retire.byte = 0; op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->addr_size/8; if ( op_bytes == 8 ) { op_bytes = def_op_bytes = 4;#ifndef __x86_64__ return X86EMUL_UNHANDLEABLE;#endif } /* Prefix bytes. */ for ( ; ; ) { switch ( b = insn_fetch_type(uint8_t) ) { case 0x66: /* operand-size override */ op_bytes = def_op_bytes ^ 6; break; case 0x67: /* address-size override */ ad_bytes = def_ad_bytes ^ (mode_64bit() ? 12 : 6); break; case 0x2e: /* CS override */ override_seg = x86_seg_cs; break; case 0x3e: /* DS override */ override_seg = x86_seg_ds; break; case 0x26: /* ES override */ override_seg = x86_seg_es; break; case 0x64: /* FS override */ override_seg = x86_seg_fs; break; case 0x65: /* GS override */ override_seg = x86_seg_gs; break; case 0x36: /* SS override */ override_seg = x86_seg_ss; break; case 0xf0: /* LOCK */ lock_prefix = 1; break; case 0xf2: /* REPNE/REPNZ */ rep_prefix = REPNE_PREFIX; break; case 0xf3: /* REP/REPE/REPZ */ rep_prefix = REPE_PREFIX; break; case 0x40 ... 0x4f: /* REX */ if ( !mode_64bit() ) goto done_prefixes; rex_prefix = b; continue; default: goto done_prefixes; } /* Any legacy prefix after a REX prefix nullifies its effect. */ rex_prefix = 0; } done_prefixes: if ( rex_prefix & 8 ) /* REX.W */ op_bytes = 8; /* Opcode byte(s). */ d = opcode_table[b]; if ( d == 0 ) { /* Two-byte opcode? */ if ( b == 0x0f ) { twobyte = 1; b = insn_fetch_type(uint8_t); d = twobyte_table[b]; } /* Unrecognised? */ if ( d == 0 ) goto cannot_emulate; } /* Lock prefix is allowed only on RMW instructions. */ generate_exception_if((d & Mov) && lock_prefix, EXC_GP, 0); /* ModRM and SIB bytes. */ if ( d & ModRM ) { modrm = insn_fetch_type(uint8_t); modrm_mod = (modrm & 0xc0) >> 6; modrm_reg = ((rex_prefix & 4) << 1) | ((modrm & 0x38) >> 3); modrm_rm = modrm & 0x07; if ( modrm_mod == 3 ) { modrm_rm |= (rex_prefix & 1) << 3; ea.type = OP_REG; ea.reg = decode_register( modrm_rm, &_regs, (d & ByteOp) && (rex_prefix == 0)); } else if ( ad_bytes == 2 ) { /* 16-bit ModR/M decode. */ switch ( modrm_rm ) { case 0: ea.mem.off = _regs.ebx + _regs.esi; break; case 1: ea.mem.off = _regs.ebx + _regs.edi; break; case 2: ea.mem.seg = x86_seg_ss; ea.mem.off = _regs.ebp + _regs.esi; break; case 3: ea.mem.seg = x86_seg_ss; ea.mem.off = _regs.ebp + _regs.edi; break; case 4: ea.mem.off = _regs.esi; break; case 5: ea.mem.off = _regs.edi; break; case 6: if ( modrm_mod == 0 ) break; ea.mem.seg = x86_seg_ss; ea.mem.off = _regs.ebp; break; case 7: ea.mem.off = _regs.ebx; break; } switch ( modrm_mod ) { case 0: if ( modrm_rm == 6 ) ea.mem.off = insn_fetch_type(int16_t); break; case 1: ea.mem.off += insn_fetch_type(int8_t); break; case 2: ea.mem.off += insn_fetch_type(int16_t); break; } ea.mem.off = truncate_ea(ea.mem.off); } else { /* 32/64-bit ModR/M decode. */ if ( modrm_rm == 4 ) { sib = insn_fetch_type(uint8_t); sib_index = ((sib >> 3) & 7) | ((rex_prefix << 2) & 8); sib_base = (sib & 7) | ((rex_prefix << 3) & 8); if ( sib_index != 4 ) ea.mem.off = *(long*)decode_register(sib_index, &_regs, 0); ea.mem.off <<= (sib >> 6) & 3; if ( (modrm_mod == 0) && ((sib_base & 7) == 5) ) ea.mem.off += insn_fetch_type(int32_t); else if ( sib_base == 4 ) { ea.mem.seg = x86_seg_ss; ea.mem.off += _regs.esp; if ( !twobyte && (b == 0x8f) ) /* POP <rm> computes its EA post increment. */ ea.mem.off += ((mode_64bit() && (op_bytes == 4)) ? 8 : op_bytes); } else if ( sib_base == 5 ) { ea.mem.seg = x86_seg_ss; ea.mem.off += _regs.ebp; } else ea.mem.off += *(long*)decode_register(sib_base, &_regs, 0); } else { modrm_rm |= (rex_prefix & 1) << 3; ea.mem.off = *(long *)decode_register(modrm_rm, &_regs, 0); if ( (modrm_rm == 5) && (modrm_mod != 0) ) ea.mem.seg = x86_seg_ss; } switch ( modrm_mod ) { case 0: if ( (modrm_rm & 7) != 5 ) break; ea.mem.off = insn_fetch_type(int32_t); if ( !mode_64bit() ) break; /* Relative to RIP of next instruction. Argh! */ ea.mem.off += _regs.eip; if ( (d & SrcMask) == SrcImm ) ea.mem.off += (d & ByteOp) ? 1 : ((op_bytes == 8) ? 4 : op_bytes); else if ( (d & SrcMask) == SrcImmByte ) ea.mem.off += 1; else if ( !twobyte && ((b & 0xfe) == 0xf6) && ((modrm_reg & 7) <= 1) ) /* Special case in Grp3: test has immediate operand. */ ea.mem.off += (d & ByteOp) ? 1 : ((op_bytes == 8) ? 4 : op_bytes); else if ( twobyte && ((b & 0xf7) == 0xa4) ) /* SHLD/SHRD with immediate byte third operand. */ ea.mem.off++; break; case 1: ea.mem.off += insn_fetch_type(int8_t); break; case 2: ea.mem.off += insn_fetch_type(int32_t); break; } ea.mem.off = truncate_ea(ea.mem.off); } } if ( override_seg != -1 ) ea.mem.seg = override_seg; /* Special instructions do their own operand decoding. */ if ( (d & DstMask) == ImplicitOps ) goto special_insn; /* Decode and fetch the source operand: register, memory or immediate. */ switch ( d & SrcMask ) { case SrcNone: break; case SrcReg: src.type = OP_REG; if ( d & ByteOp ) { src.reg = decode_register(modrm_reg, &_regs, (rex_prefix == 0)); src.val = *(uint8_t *)src.reg; src.bytes = 1; } else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?