debuggers.hg
changeset 16499:d40788f07a4f
x86_emulate: Emulate far call/jmp. This completes emulation of Grp5.
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 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, ®, 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, ®, 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;