ia64/xen-unstable

changeset 16461:d40788f07a4f

x86_emulate: Emulate far call/jmp. This completes emulation of Grp5.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Sun Nov 25 12:43:13 2007 +0000 (2007-11-25)
parents a194083696d5
children f6a587e3d5c9
files xen/arch/x86/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate.c	Sun Nov 25 11:45:02 2007 +0000
     1.2 +++ b/xen/arch/x86/x86_emulate.c	Sun Nov 25 12:43:13 2007 +0000
     1.3 @@ -126,7 +126,8 @@ static uint8_t opcode_table[256] = {
     1.4      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     1.5      ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     1.6      /* 0x98 - 0x9F */
     1.7 -    ImplicitOps, ImplicitOps, 0, 0, 0, 0, ImplicitOps, ImplicitOps,
     1.8 +    ImplicitOps, ImplicitOps, ImplicitOps, 0,
     1.9 +    0, 0, ImplicitOps, ImplicitOps,
    1.10      /* 0xA0 - 0xA7 */
    1.11      ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
    1.12      ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
    1.13 @@ -1687,6 +1688,33 @@ x86_emulate(
    1.14              if ( (modrm_reg & 7) == 2 )
    1.15                  goto push; /* call */
    1.16              break;
    1.17 +        case 3: /* call (far, absolute indirect) */
    1.18 +        case 5: /* jmp (far, absolute indirect) */ {
    1.19 +            unsigned long sel, eip = dst.val;
    1.20 +
    1.21 +            if ( (rc = ops->read(dst.mem.seg, dst.mem.off+dst.bytes,
    1.22 +                                 &sel, 2, ctxt)) )
    1.23 +                goto done;
    1.24 +
    1.25 +            if ( (modrm_reg & 7) == 3 ) /* call */
    1.26 +            {
    1.27 +                struct segment_register reg;
    1.28 +                fail_if(ops->read_segment == NULL);
    1.29 +                if ( (rc = ops->read_segment(x86_seg_cs, &reg, ctxt)) ||
    1.30 +                     (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
    1.31 +                                      reg.sel, op_bytes, ctxt)) ||
    1.32 +                     (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
    1.33 +                                      _regs.eip, op_bytes, ctxt)) )
    1.34 +                    goto done;
    1.35 +            }
    1.36 +
    1.37 +            if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 )
    1.38 +                goto done;
    1.39 +            _regs.eip = eip;
    1.40 +
    1.41 +            dst.type = OP_NONE;
    1.42 +            break;
    1.43 +        }
    1.44          case 6: /* push */
    1.45              /* 64-bit mode: PUSH defaults to a 64-bit operand. */
    1.46              if ( mode_64bit() && (dst.bytes == 4) )
    1.47 @@ -2024,6 +2052,30 @@ x86_emulate(
    1.48          }
    1.49          break;
    1.50  
    1.51 +    case 0x9a: /* call (far, absolute) */ {
    1.52 +        struct segment_register reg;
    1.53 +        uint16_t sel;
    1.54 +        uint32_t eip;
    1.55 +
    1.56 +        fail_if(ops->read_segment == NULL);
    1.57 +        generate_exception_if(mode_64bit(), EXC_UD);
    1.58 +
    1.59 +        eip = insn_fetch_bytes(op_bytes);
    1.60 +        sel = insn_fetch_type(uint16_t);
    1.61 +
    1.62 +        if ( (rc = ops->read_segment(x86_seg_cs, &reg, ctxt)) ||
    1.63 +             (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
    1.64 +                              reg.sel, op_bytes, ctxt)) ||
    1.65 +             (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
    1.66 +                              _regs.eip, op_bytes, ctxt)) )
    1.67 +            goto done;
    1.68 +
    1.69 +        if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 )
    1.70 +            goto done;
    1.71 +        _regs.eip = eip;
    1.72 +        break;
    1.73 +    }
    1.74 +
    1.75      case 0x9e: /* sahf */
    1.76          *(uint8_t *)_regs.eflags = (((uint8_t *)&_regs.eax)[1] & 0xd7) | 0x02;
    1.77          break;