ia64/xen-unstable

changeset 16491:cca2f2fb857d

x86_emulate: Emulate ENTER and LEAVE instructions.
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;