debuggers.hg
changeset 16520:cca2f2fb857d
x86_emulate: Emulate ENTER and LEAVE instructions.
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 | Wed Nov 28 12:44:19 2007 +0000 (2007-11-28) |
parents | 3fdbdd131fc7 |
children | 43b7d24acf9c |
files | xen/arch/x86/x86_emulate.c |
line diff
1.1 --- a/xen/arch/x86/x86_emulate.c Wed Nov 28 12:42:17 2007 +0000 1.2 +++ b/xen/arch/x86/x86_emulate.c Wed Nov 28 12:44:19 2007 +0000 1.3 @@ -152,7 +152,7 @@ static uint8_t opcode_table[256] = { 1.4 DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, 1.5 ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov, 1.6 /* 0xC8 - 0xCF */ 1.7 - 0, 0, ImplicitOps, ImplicitOps, 1.8 + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, 1.9 ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, 1.10 /* 0xD0 - 0xD7 */ 1.11 ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, 1.12 @@ -2263,6 +2263,63 @@ x86_emulate( 1.13 break; 1.14 } 1.15 1.16 + case 0xc8: /* enter imm16,imm8 */ { 1.17 + uint16_t size = insn_fetch_type(uint16_t); 1.18 + uint8_t depth = insn_fetch_type(uint8_t) & 31; 1.19 + int i; 1.20 + 1.21 + dst.type = OP_REG; 1.22 + dst.bytes = (mode_64bit() && (op_bytes == 4)) ? 8 : op_bytes; 1.23 + dst.reg = (unsigned long *)&_regs.ebp; 1.24 + if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes), 1.25 + _regs.ebp, dst.bytes, ctxt)) ) 1.26 + goto done; 1.27 + dst.val = _regs.esp; 1.28 + 1.29 + if ( depth > 0 ) 1.30 + { 1.31 + for ( i = 1; i < depth; i++ ) 1.32 + { 1.33 + unsigned long ebp, temp_data; 1.34 + ebp = _truncate_ea(_regs.ebp - i*dst.bytes, ctxt->sp_size/8); 1.35 + if ( (rc = ops->read(x86_seg_ss, ebp, 1.36 + &temp_data, dst.bytes, ctxt)) || 1.37 + (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes), 1.38 + temp_data, dst.bytes, ctxt)) ) 1.39 + goto done; 1.40 + } 1.41 + if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes), 1.42 + dst.val, dst.bytes, ctxt)) ) 1.43 + goto done; 1.44 + } 1.45 + 1.46 + sp_pre_dec(size); 1.47 + break; 1.48 + } 1.49 + 1.50 + case 0xc9: /* leave */ 1.51 + /* First writeback, to %%esp. */ 1.52 + dst.type = OP_REG; 1.53 + dst.bytes = (mode_64bit() && (op_bytes == 4)) ? 8 : op_bytes; 1.54 + dst.reg = (unsigned long *)&_regs.esp; 1.55 + dst.val = _regs.ebp; 1.56 + 1.57 + /* Flush first writeback, since there is a second. */ 1.58 + switch ( dst.bytes ) 1.59 + { 1.60 + case 1: *(uint8_t *)dst.reg = (uint8_t)dst.val; break; 1.61 + case 2: *(uint16_t *)dst.reg = (uint16_t)dst.val; break; 1.62 + case 4: *dst.reg = (uint32_t)dst.val; break; /* 64b: zero-ext */ 1.63 + case 8: *dst.reg = dst.val; break; 1.64 + } 1.65 + 1.66 + /* Second writeback, to %%ebp. */ 1.67 + dst.reg = (unsigned long *)&_regs.ebp; 1.68 + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes), 1.69 + &dst.val, dst.bytes, ctxt)) ) 1.70 + goto done; 1.71 + break; 1.72 + 1.73 case 0xca: /* ret imm16 (far) */ 1.74 case 0xcb: /* ret (far) */ { 1.75 int offset = (b == 0xca) ? insn_fetch_type(uint16_t) : 0;