debuggers.hg
changeset 16502:7c6944d861b2
x86_emulate: Emulate IRET.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Sun Nov 25 18:06:30 2007 +0000 (2007-11-25) |
parents | 502f5b9469c3 |
children | 6d129d093394 |
files | xen/arch/x86/x86_emulate.c |
line diff
1.1 --- a/xen/arch/x86/x86_emulate.c Sun Nov 25 18:05:56 2007 +0000 1.2 +++ b/xen/arch/x86/x86_emulate.c Sun Nov 25 18:06:30 2007 +0000 1.3 @@ -149,7 +149,7 @@ static uint8_t opcode_table[256] = { 1.4 ImplicitOps, ImplicitOps, 1.5 0, 0, ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov, 1.6 /* 0xC8 - 0xCF */ 1.7 - 0, 0, 0, 0, ImplicitOps, ImplicitOps, ImplicitOps, 0, 1.8 + 0, 0, 0, 0, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, 1.9 /* 0xD0 - 0xD7 */ 1.10 ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 1.11 ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 1.12 @@ -2214,6 +2214,33 @@ x86_emulate( 1.13 src.val = EXC_OF; 1.14 goto swint; 1.15 1.16 + case 0xcf: /* iret */ { 1.17 + unsigned long cs, eip, eflags; 1.18 + uint32_t mask = EFLG_VIP | EFLG_VIF | EFLG_VM; 1.19 + if ( !mode_iopl() ) 1.20 + mask |= EFLG_IOPL; 1.21 + fail_if(!in_realmode(ctxt, ops)); 1.22 + fail_if(ops->write_rflags == NULL); 1.23 + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes), 1.24 + &eip, op_bytes, ctxt)) || 1.25 + (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes), 1.26 + &cs, op_bytes, ctxt)) || 1.27 + (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes), 1.28 + &eflags, op_bytes, ctxt)) ) 1.29 + goto done; 1.30 + if ( op_bytes == 2 ) 1.31 + eflags = (uint16_t)eflags | (_regs.eflags & 0xffff0000u); 1.32 + eflags &= 0x257fd5; 1.33 + _regs.eflags &= mask; 1.34 + _regs.eflags |= (uint32_t)(eflags & ~mask) | 0x02; 1.35 + if ( (rc = ops->write_rflags(_regs.eflags, ctxt)) != 0 ) 1.36 + goto done; 1.37 + _regs.eip = eip; 1.38 + if ( (rc = load_seg(x86_seg_cs, (uint16_t)cs, ctxt, ops)) != 0 ) 1.39 + goto done; 1.40 + break; 1.41 + } 1.42 + 1.43 case 0xd4: /* aam */ { 1.44 unsigned int base = insn_fetch_type(uint8_t); 1.45 uint8_t al = _regs.eax;