[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86_emulate: Emulate far call/jmp. This completes emulation of Grp5.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1195994593 0
# Node ID d40788f07a4f40ac95c1f297f808c63b85baa3ff
# Parent  a194083696d5dbd9b7509d35924e48aa05678607
x86_emulate: Emulate far call/jmp. This completes emulation of Grp5.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/x86_emulate.c |   54 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 53 insertions(+), 1 deletion(-)

diff -r a194083696d5 -r d40788f07a4f xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Sun Nov 25 11:45:02 2007 +0000
+++ b/xen/arch/x86/x86_emulate.c        Sun Nov 25 12:43:13 2007 +0000
@@ -126,7 +126,8 @@ static uint8_t opcode_table[256] = {
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
     /* 0x98 - 0x9F */
-    ImplicitOps, ImplicitOps, 0, 0, 0, 0, ImplicitOps, ImplicitOps,
+    ImplicitOps, ImplicitOps, ImplicitOps, 0,
+    0, 0, ImplicitOps, ImplicitOps,
     /* 0xA0 - 0xA7 */
     ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
     ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
@@ -1687,6 +1688,33 @@ x86_emulate(
             if ( (modrm_reg & 7) == 2 )
                 goto push; /* call */
             break;
+        case 3: /* call (far, absolute indirect) */
+        case 5: /* jmp (far, absolute indirect) */ {
+            unsigned long sel, eip = dst.val;
+
+            if ( (rc = ops->read(dst.mem.seg, dst.mem.off+dst.bytes,
+                                 &sel, 2, ctxt)) )
+                goto done;
+
+            if ( (modrm_reg & 7) == 3 ) /* call */
+            {
+                struct segment_register reg;
+                fail_if(ops->read_segment == NULL);
+                if ( (rc = ops->read_segment(x86_seg_cs, &reg, ctxt)) ||
+                     (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
+                                      reg.sel, op_bytes, ctxt)) ||
+                     (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
+                                      _regs.eip, op_bytes, ctxt)) )
+                    goto done;
+            }
+
+            if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 )
+                goto done;
+            _regs.eip = eip;
+
+            dst.type = OP_NONE;
+            break;
+        }
         case 6: /* push */
             /* 64-bit mode: PUSH defaults to a 64-bit operand. */
             if ( mode_64bit() && (dst.bytes == 4) )
@@ -2023,6 +2051,30 @@ x86_emulate(
             break;
         }
         break;
+
+    case 0x9a: /* call (far, absolute) */ {
+        struct segment_register reg;
+        uint16_t sel;
+        uint32_t eip;
+
+        fail_if(ops->read_segment == NULL);
+        generate_exception_if(mode_64bit(), EXC_UD);
+
+        eip = insn_fetch_bytes(op_bytes);
+        sel = insn_fetch_type(uint16_t);
+
+        if ( (rc = ops->read_segment(x86_seg_cs, &reg, ctxt)) ||
+             (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
+                              reg.sel, op_bytes, ctxt)) ||
+             (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
+                              _regs.eip, op_bytes, ctxt)) )
+            goto done;
+
+        if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 )
+            goto done;
+        _regs.eip = eip;
+        break;
+    }
 
     case 0x9e: /* sahf */
         *(uint8_t *)_regs.eflags = (((uint8_t *)&_regs.eax)[1] & 0xd7) | 0x02;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.