|  | /****************************************************************************** | 
|  | * x86_emulate.c | 
|  | * | 
|  | * Generic x86 (32-bit and 64-bit) instruction decoder and emulator. | 
|  | * | 
|  | * Copyright (c) 2005 Keir Fraser | 
|  | * | 
|  | * Linux coding style, mod r/m decoder, segment base fixes, real-mode | 
|  | * privieged instructions: | 
|  | * | 
|  | * Copyright (C) 2006 Qumranet | 
|  | * | 
|  | *   Avi Kivity <avi@qumranet.com> | 
|  | *   Yaniv Kamay <yaniv@qumranet.com> | 
|  | * | 
|  | * From: xen-unstable 10676:af9809f51f81a3c43f276f00c81a52ef558afda4 | 
|  | */ | 
|  |  | 
|  | #define DEBUG | 
|  | #include <kmalloc.h> | 
|  | #include <string.h> | 
|  | #include <stdio.h> | 
|  | #include <assert.h> | 
|  | #include <error.h> | 
|  | #include <pmap.h> | 
|  | #include <sys/queue.h> | 
|  | #include <smp.h> | 
|  | #include <kref.h> | 
|  | #include <atomic.h> | 
|  | #include <alarm.h> | 
|  | #include <event.h> | 
|  | #include <umem.h> | 
|  | #include <devalarm.h> | 
|  | #include <arch/types.h> | 
|  | #include <arch/vm.h> | 
|  | #include <arch/emulate.h> | 
|  | #include <arch/vmdebug.h> | 
|  |  | 
|  | /* | 
|  | * Opcode effective-address decode tables. | 
|  | * Note that we only emulate instructions that have at least one memory | 
|  | * operand (excluding implicit stack references). We assume that stack | 
|  | * references and instruction fetches will never occur in special memory | 
|  | * areas that require emulation. So, for example, 'mov <imm>,<reg>' need | 
|  | * not be handled. | 
|  | */ | 
|  |  | 
|  | /* Operand sizes: 8-bit operands or specified/overridden size. */ | 
|  | #define ByteOp      (1<<0)	/* 8-bit operands. */ | 
|  | /* Destination operand type. */ | 
|  | #define ImplicitOps (1<<1)	/* Implicit in opcode. No generic decode. */ | 
|  | #define DstReg      (2<<1)	/* Register operand. */ | 
|  | #define DstMem      (3<<1)	/* Memory operand. */ | 
|  | #define DstMask     (3<<1) | 
|  | /* Source operand type. */ | 
|  | #define SrcNone     (0<<3)	/* No source operand. */ | 
|  | #define SrcImplicit (0<<3)	/* Source operand is implicit in the opcode. */ | 
|  | #define SrcReg      (1<<3)	/* Register operand. */ | 
|  | #define SrcMem      (2<<3)	/* Memory operand. */ | 
|  | #define SrcMem16    (3<<3)	/* Memory operand (16-bit). */ | 
|  | #define SrcMem32    (4<<3)	/* Memory operand (32-bit). */ | 
|  | #define SrcImm      (5<<3)	/* Immediate operand. */ | 
|  | #define SrcImmByte  (6<<3)	/* 8-bit sign-extended immediate operand. */ | 
|  | #define SrcMask     (7<<3) | 
|  | /* Generic ModRM decode. */ | 
|  | #define ModRM       (1<<6) | 
|  | /* Destination is only written; never read. */ | 
|  | #define Mov         (1<<7) | 
|  |  | 
|  | static uint8_t opcode_table[256] = { | 
|  | /* 0x00 - 0x07 */ | 
|  | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 
|  | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 
|  | 0, 0, 0, 0, | 
|  | /* 0x08 - 0x0F */ | 
|  | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 
|  | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 
|  | 0, 0, 0, 0, | 
|  | /* 0x10 - 0x17 */ | 
|  | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 
|  | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 
|  | 0, 0, 0, 0, | 
|  | /* 0x18 - 0x1F */ | 
|  | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 
|  | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 
|  | 0, 0, 0, 0, | 
|  | /* 0x20 - 0x27 */ | 
|  | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 
|  | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 
|  | 0, 0, 0, 0, | 
|  | /* 0x28 - 0x2F */ | 
|  | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 
|  | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 
|  | 0, 0, 0, 0, | 
|  | /* 0x30 - 0x37 */ | 
|  | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 
|  | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 
|  | 0, 0, 0, 0, | 
|  | /* 0x38 - 0x3F */ | 
|  | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 
|  | ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, | 
|  | 0, 0, 0, 0, | 
|  | /* 0x40 - 0x4F */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0x50 - 0x5F */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0x60 - 0x6F */ | 
|  | 0, 0, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ , | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0x70 - 0x7F */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0x80 - 0x87 */ | 
|  | ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM, | 
|  | ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, | 
|  | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 
|  | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, | 
|  | /* 0x88 - 0x8F */ | 
|  | ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov, | 
|  | ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | 
|  | 0, 0, 0, DstMem | SrcNone | ModRM | Mov, | 
|  | /* 0x90 - 0x9F */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0xA0 - 0xA7 */ | 
|  | ByteOp | DstReg | SrcMem | Mov, DstReg | SrcMem | Mov, | 
|  | ByteOp | DstMem | SrcReg | Mov, DstMem | SrcReg | Mov, | 
|  | ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, | 
|  | ByteOp | ImplicitOps, ImplicitOps, | 
|  | /* 0xA8 - 0xAF */ | 
|  | 0, 0, ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, | 
|  | ByteOp | ImplicitOps | Mov, ImplicitOps | Mov, | 
|  | ByteOp | ImplicitOps, ImplicitOps, | 
|  | /* 0xB0 - 0xBF */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0xC0 - 0xC7 */ | 
|  | ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 0, 0, | 
|  | 0, 0, ByteOp | DstMem | SrcImm | ModRM | Mov, | 
|  | DstMem | SrcImm | ModRM | Mov, | 
|  | /* 0xC8 - 0xCF */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0xD0 - 0xD7 */ | 
|  | ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, | 
|  | ByteOp | DstMem | SrcImplicit | ModRM, DstMem | SrcImplicit | ModRM, | 
|  | 0, 0, 0, 0, | 
|  | /* 0xD8 - 0xDF */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0xE0 - 0xEF */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0xF0 - 0xF7 */ | 
|  | 0, 0, 0, 0, | 
|  | 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, | 
|  | /* 0xF8 - 0xFF */ | 
|  | 0, 0, 0, 0, | 
|  | 0, 0, ByteOp | DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM | 
|  | }; | 
|  |  | 
|  | static uint8_t twobyte_table[256] = { | 
|  | /* 0x00 - 0x0F */ | 
|  | 0, SrcMem | ModRM | DstReg | Mov, 0, 0, 0, 0, 0, 0, | 
|  | 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, | 
|  | /* 0x10 - 0x1F */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0x20 - 0x2F */ | 
|  | ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0x30 - 0x3F */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0x40 - 0x47 */ | 
|  | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | 
|  | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | 
|  | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | 
|  | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | 
|  | /* 0x48 - 0x4F */ | 
|  | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | 
|  | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | 
|  | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | 
|  | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, | 
|  | /* 0x50 - 0x5F */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0x60 - 0x6F */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0x70 - 0x7F */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0x80 - 0x8F */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0x90 - 0x9F */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0xA0 - 0xA7 */ | 
|  | 0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0, | 
|  | /* 0xA8 - 0xAF */ | 
|  | 0, 0, 0, DstMem | SrcReg | ModRM, 0, 0, 0, 0, | 
|  | /* 0xB0 - 0xB7 */ | 
|  | ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0, | 
|  | DstMem | SrcReg | ModRM, | 
|  | 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, | 
|  | DstReg | SrcMem16 | ModRM | Mov, | 
|  | /* 0xB8 - 0xBF */ | 
|  | 0, 0, DstMem | SrcImmByte | ModRM, DstMem | SrcReg | ModRM, | 
|  | 0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov, | 
|  | DstReg | SrcMem16 | ModRM | Mov, | 
|  | /* 0xC0 - 0xCF */ | 
|  | 0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0xD0 - 0xDF */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0xE0 - 0xEF */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 
|  | /* 0xF0 - 0xFF */ | 
|  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | 
|  | }; | 
|  |  | 
|  | /* Type, address-of, and value of an instruction's operand. */ | 
|  | struct operand { | 
|  | enum { OP_REG, OP_MEM, OP_IMM } type; | 
|  | unsigned int bytes; | 
|  | unsigned long val, orig_val, *ptr; | 
|  | }; | 
|  |  | 
|  | /* EFLAGS bit definitions. */ | 
|  | #define EFLG_OF (1<<11) | 
|  | #define EFLG_DF (1<<10) | 
|  | #define EFLG_SF (1<<7) | 
|  | #define EFLG_ZF (1<<6) | 
|  | #define EFLG_AF (1<<4) | 
|  | #define EFLG_PF (1<<2) | 
|  | #define EFLG_CF (1<<0) | 
|  |  | 
|  | /* | 
|  | * Instruction emulation: | 
|  | * Most instructions are emulated directly via a fragment of inline assembly | 
|  | * code. This allows us to save/restore EFLAGS and thus very easily pick up | 
|  | * any modified flags. | 
|  | */ | 
|  |  | 
|  | #if defined(__x86_64__) | 
|  | #define _LO32 "k"		/* force 32-bit operand */ | 
|  | #define _STK  "%%rsp"		/* stack pointer */ | 
|  | #elif defined(__i386__) | 
|  | #define _LO32 ""		/* force 32-bit operand */ | 
|  | #define _STK  "%%esp"		/* stack pointer */ | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * These EFLAGS bits are restored from saved value during emulation, and | 
|  | * any changes are written back to the saved value after emulation. | 
|  | */ | 
|  | #define EFLAGS_MASK (EFLG_OF|EFLG_SF|EFLG_ZF|EFLG_AF|EFLG_PF|EFLG_CF) | 
|  |  | 
|  | /* Before executing instruction: restore necessary bits in EFLAGS. */ | 
|  | #define _PRE_EFLAGS(_sav, _msk, _tmp) \ | 
|  | /* EFLAGS = (_sav & _msk) | (EFLAGS & ~_msk); */	\ | 
|  | "push %"_sav"; "					\ | 
|  | "movl %"_msk",%"_LO32 _tmp"; "				\ | 
|  | "andl %"_LO32 _tmp",("_STK"); "				\ | 
|  | "pushf; "						\ | 
|  | "notl %"_LO32 _tmp"; "					\ | 
|  | "andl %"_LO32 _tmp",("_STK"); "				\ | 
|  | "pop  %"_tmp"; "					\ | 
|  | "orl  %"_LO32 _tmp",("_STK"); "				\ | 
|  | "popf; "						\ | 
|  | /* _sav &= ~msk; */					\ | 
|  | "movl %"_msk",%"_LO32 _tmp"; "				\ | 
|  | "notl %"_LO32 _tmp"; "					\ | 
|  | "andl %"_LO32 _tmp",%"_sav"; " | 
|  |  | 
|  | /* After executing instruction: write-back necessary bits in EFLAGS. */ | 
|  | #define _POST_EFLAGS(_sav, _msk, _tmp) \ | 
|  | /* _sav |= EFLAGS & _msk; */		\ | 
|  | "pushf; "				\ | 
|  | "pop  %"_tmp"; "			\ | 
|  | "andl %"_msk",%"_LO32 _tmp"; "		\ | 
|  | "orl  %"_LO32 _tmp",%"_sav"; " | 
|  |  | 
|  | /* Raw emulation: instruction has two explicit operands. */ | 
|  | #define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \ | 
|  | do { 								    \ | 
|  | unsigned long _tmp;					    \ | 
|  | \ | 
|  | switch ((_dst).bytes) {					    \ | 
|  | case 2:							    \ | 
|  | __asm__ __volatile__ (				    \ | 
|  | _PRE_EFLAGS("0","4","2")		    \ | 
|  | _op"w %"_wx"3,%1; "			    \ | 
|  | _POST_EFLAGS("0","4","2")		    \ | 
|  | : "=m" (_eflags), "=m" ((_dst).val),        \ | 
|  | "=&r" (_tmp)				    \ | 
|  | : _wy ((_src).val), "i" (EFLAGS_MASK) );    \ | 
|  | break;						    \ | 
|  | case 4:							    \ | 
|  | __asm__ __volatile__ (				    \ | 
|  | _PRE_EFLAGS("0","4","2")		    \ | 
|  | _op"l %"_lx"3,%1; "			    \ | 
|  | _POST_EFLAGS("0","4","2")		    \ | 
|  | : "=m" (_eflags), "=m" ((_dst).val),	    \ | 
|  | "=&r" (_tmp)				    \ | 
|  | : _ly ((_src).val), "i" (EFLAGS_MASK) );    \ | 
|  | break;						    \ | 
|  | case 8:							    \ | 
|  | __emulate_2op_8byte(_op, _src, _dst,		    \ | 
|  | _eflags, _qx, _qy);		    \ | 
|  | break;						    \ | 
|  | }							    \ | 
|  | } while (0) | 
|  |  | 
|  | #define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \ | 
|  | do {								     \ | 
|  | unsigned long _tmp;					     \ | 
|  | switch ( (_dst).bytes )					     \ | 
|  | {							     \ | 
|  | case 1:							     \ | 
|  | __asm__ __volatile__ (				     \ | 
|  | _PRE_EFLAGS("0","4","2")		     \ | 
|  | _op"b %"_bx"3,%1; "			     \ | 
|  | _POST_EFLAGS("0","4","2")		     \ | 
|  | : "=m" (_eflags), "=m" ((_dst).val),	     \ | 
|  | "=&r" (_tmp)				     \ | 
|  | : _by ((_src).val), "i" (EFLAGS_MASK) );     \ | 
|  | break;						     \ | 
|  | default:						     \ | 
|  | __emulate_2op_nobyte(_op, _src, _dst, _eflags,	     \ | 
|  | _wx, _wy, _lx, _ly, _qx, _qy);  \ | 
|  | break;						     \ | 
|  | }							     \ | 
|  | } while (0) | 
|  |  | 
|  | /* Source operand is byte-sized and may be restricted to just %cl. */ | 
|  | #define emulate_2op_SrcB(_op, _src, _dst, _eflags)                      \ | 
|  | __emulate_2op(_op, _src, _dst, _eflags,				\ | 
|  | "b", "c", "b", "c", "b", "c", "b", "c") | 
|  |  | 
|  | /* Source operand is byte, word, long or quad sized. */ | 
|  | #define emulate_2op_SrcV(_op, _src, _dst, _eflags)                      \ | 
|  | __emulate_2op(_op, _src, _dst, _eflags,				\ | 
|  | "b", "q", "w", "r", _LO32, "r", "", "r") | 
|  |  | 
|  | /* Source operand is word, long or quad sized. */ | 
|  | #define emulate_2op_SrcV_nobyte(_op, _src, _dst, _eflags)               \ | 
|  | __emulate_2op_nobyte(_op, _src, _dst, _eflags,			\ | 
|  | "w", "r", _LO32, "r", "", "r") | 
|  |  | 
|  | /* Instruction has only one explicit operand (no source operand). */ | 
|  | #define emulate_1op(_op, _dst, _eflags)                                    \ | 
|  | do {								\ | 
|  | unsigned long _tmp;					\ | 
|  | \ | 
|  | switch ( (_dst).bytes )					\ | 
|  | {							\ | 
|  | case 1:							\ | 
|  | __asm__ __volatile__ (				\ | 
|  | _PRE_EFLAGS("0","3","2")		\ | 
|  | _op"b %1; "				\ | 
|  | _POST_EFLAGS("0","3","2")		\ | 
|  | : "=m" (_eflags), "=m" ((_dst).val),	\ | 
|  | "=&r" (_tmp)				\ | 
|  | : "i" (EFLAGS_MASK) );			\ | 
|  | break;						\ | 
|  | case 2:							\ | 
|  | __asm__ __volatile__ (				\ | 
|  | _PRE_EFLAGS("0","3","2")		\ | 
|  | _op"w %1; "				\ | 
|  | _POST_EFLAGS("0","3","2")		\ | 
|  | : "=m" (_eflags), "=m" ((_dst).val),	\ | 
|  | "=&r" (_tmp)				\ | 
|  | : "i" (EFLAGS_MASK) );			\ | 
|  | break;						\ | 
|  | case 4:							\ | 
|  | __asm__ __volatile__ (				\ | 
|  | _PRE_EFLAGS("0","3","2")		\ | 
|  | _op"l %1; "				\ | 
|  | _POST_EFLAGS("0","3","2")		\ | 
|  | : "=m" (_eflags), "=m" ((_dst).val),	\ | 
|  | "=&r" (_tmp)				\ | 
|  | : "i" (EFLAGS_MASK) );			\ | 
|  | break;						\ | 
|  | case 8:							\ | 
|  | __emulate_1op_8byte(_op, _dst, _eflags);	\ | 
|  | break;						\ | 
|  | }							\ | 
|  | } while (0) | 
|  |  | 
|  | /* Emulate an instruction with quadword operands (x86/64 only). */ | 
|  | #if defined(__x86_64__) | 
|  | #define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy)           \ | 
|  | do {								  \ | 
|  | __asm__ __volatile__ (					  \ | 
|  | _PRE_EFLAGS("0","4","2")			  \ | 
|  | _op"q %"_qx"3,%1; "				  \ | 
|  | _POST_EFLAGS("0","4","2")			  \ | 
|  | : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ | 
|  | : _qy ((_src).val), "i" (EFLAGS_MASK) );	  \ | 
|  | } while (0) | 
|  |  | 
|  | #define __emulate_1op_8byte(_op, _dst, _eflags)                           \ | 
|  | do {								  \ | 
|  | __asm__ __volatile__ (					  \ | 
|  | _PRE_EFLAGS("0","3","2")			  \ | 
|  | _op"q %1; "					  \ | 
|  | _POST_EFLAGS("0","3","2")			  \ | 
|  | : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ | 
|  | : "i" (EFLAGS_MASK) );				  \ | 
|  | } while (0) | 
|  |  | 
|  | #elif defined(__i386__) | 
|  | #define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy) | 
|  | #define __emulate_1op_8byte(_op, _dst, _eflags) | 
|  | #endif				/* __i386__ */ | 
|  |  | 
|  | /* Fetch next part of the instruction being emulated. */ | 
|  | #define insn_fetch(_type, _size, _eip)                                  \ | 
|  | ({	unsigned long _x;						\ | 
|  | rc = ops->read_std((unsigned long)(_eip) + ctxt->cs_base, &_x,	\ | 
|  | (_size), ctxt);       \ | 
|  | if ( rc != 0 )							\ | 
|  | goto done;						\ | 
|  | (_eip) += (_size);						\ | 
|  | (_type)_x;							\ | 
|  | }) | 
|  |  | 
|  | /* Access/update address held in a register, based on addressing mode. */ | 
|  | #define register_address(base, reg)                                     \ | 
|  | ((base) + ((ad_bytes == sizeof(unsigned long)) ? (reg) :	\ | 
|  | ((reg) & ((1UL << (ad_bytes << 3)) - 1)))) | 
|  |  | 
|  | #define register_address_increment(reg, inc)                            \ | 
|  | do {								\ | 
|  | /* signed type ensures sign extension to long */        \ | 
|  | int _inc = (inc);					\ | 
|  | if ( ad_bytes == sizeof(unsigned long) )		\ | 
|  | (reg) += _inc;					\ | 
|  | else							\ | 
|  | (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \ | 
|  | (((reg) + _inc) & ((1UL << (ad_bytes << 3)) - 1)); \ | 
|  | } while (0) | 
|  |  | 
|  | void *decode_register(uint8_t modrm_reg, unsigned long *regs, | 
|  | int highbyte_regs) | 
|  | { | 
|  | void *p; | 
|  |  | 
|  | p = ®s[modrm_reg]; | 
|  | if (highbyte_regs && modrm_reg >= 4 && modrm_reg < 8) | 
|  | p = (unsigned char *)®s[modrm_reg & 3] + 1; | 
|  | return p; | 
|  | } | 
|  |  | 
|  | static int read_descriptor(struct x86_emulate_ctxt *ctxt, | 
|  | struct x86_emulate_ops *ops, | 
|  | void *ptr, | 
|  | uint16_t *size, unsigned long *address, int op_bytes) | 
|  | { | 
|  | int rc; | 
|  |  | 
|  | if (op_bytes == 2) | 
|  | op_bytes = 3; | 
|  | *address = 0; | 
|  | rc = ops->read_std((unsigned long)ptr, (unsigned long *)size, 2, ctxt); | 
|  | if (rc) | 
|  | return rc; | 
|  | rc = ops->read_std((unsigned long)ptr + 2, address, op_bytes, ctxt); | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | int | 
|  | x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | 
|  | { | 
|  | uint8_t b, d, sib, twobyte = 0, rex_prefix = 0; | 
|  | uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; | 
|  | unsigned long *override_base = NULL; | 
|  | unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i; | 
|  | int rc = 0; | 
|  | struct operand src, dst; | 
|  | unsigned long cr2 = ctxt->cr2; | 
|  | int mode = ctxt->mode; | 
|  | unsigned long modrm_ea; | 
|  | int use_modrm_ea, index_reg = 0, base_reg = 0, scale, rip_relative = 0; | 
|  |  | 
|  | /* Shadow copy of register state. Committed on successful emulation. */ | 
|  | unsigned long _regs[NR_VCPU_REGS]; | 
|  | unsigned long _eip = ctxt->vcpu->rip, _eflags = ctxt->eflags; | 
|  | unsigned long modrm_val = 0; | 
|  |  | 
|  | memcpy(_regs, ctxt->vcpu->regs, sizeof _regs); | 
|  |  | 
|  | switch (mode) { | 
|  | case X86EMUL_MODE_REAL: | 
|  | case X86EMUL_MODE_PROT16: | 
|  | op_bytes = ad_bytes = 2; | 
|  | break; | 
|  | case X86EMUL_MODE_PROT32: | 
|  | op_bytes = ad_bytes = 4; | 
|  | break; | 
|  | #ifdef __x86_64__ | 
|  | case X86EMUL_MODE_PROT64: | 
|  | op_bytes = 4; | 
|  | ad_bytes = 8; | 
|  | break; | 
|  | #endif | 
|  | default: | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | /* Legacy prefixes. */ | 
|  | for (i = 0; i < 8; i++) { | 
|  | switch (b = insn_fetch(uint8_t, 1, _eip)) { | 
|  | case 0x66:	/* operand-size override */ | 
|  | op_bytes ^= 6;	/* switch between 2/4 bytes */ | 
|  | break; | 
|  | case 0x67:	/* address-size override */ | 
|  | if (mode == X86EMUL_MODE_PROT64) | 
|  | ad_bytes ^= 12;	/* switch between 4/8 bytes */ | 
|  | else | 
|  | ad_bytes ^= 6;	/* switch between 2/4 bytes */ | 
|  | break; | 
|  | case 0x2e:	/* CS override */ | 
|  | override_base = &ctxt->cs_base; | 
|  | break; | 
|  | case 0x3e:	/* DS override */ | 
|  | override_base = &ctxt->ds_base; | 
|  | break; | 
|  | case 0x26:	/* ES override */ | 
|  | override_base = &ctxt->es_base; | 
|  | break; | 
|  | case 0x64:	/* FS override */ | 
|  | override_base = &ctxt->fs_base; | 
|  | break; | 
|  | case 0x65:	/* GS override */ | 
|  | override_base = &ctxt->gs_base; | 
|  | break; | 
|  | case 0x36:	/* SS override */ | 
|  | override_base = &ctxt->ss_base; | 
|  | break; | 
|  | case 0xf0:	/* LOCK */ | 
|  | lock_prefix = 1; | 
|  | break; | 
|  | case 0xf3:	/* REP/REPE/REPZ */ | 
|  | rep_prefix = 1; | 
|  | break; | 
|  | case 0xf2:	/* REPNE/REPNZ */ | 
|  | break; | 
|  | default: | 
|  | goto done_prefixes; | 
|  | } | 
|  | } | 
|  |  | 
|  | done_prefixes: | 
|  |  | 
|  | /* REX prefix. */ | 
|  | if ((mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40)) { | 
|  | rex_prefix = b; | 
|  | if (b & 8) | 
|  | op_bytes = 8;	/* REX.W */ | 
|  | modrm_reg = (b & 4) << 1;	/* REX.R */ | 
|  | index_reg = (b & 2) << 2; /* REX.X */ | 
|  | modrm_rm = base_reg = (b & 1) << 3; /* REG.B */ | 
|  | b = insn_fetch(uint8_t, 1, _eip); | 
|  | } | 
|  |  | 
|  | /* Opcode byte(s). */ | 
|  | d = opcode_table[b]; | 
|  | if (d == 0) { | 
|  | /* Two-byte opcode? */ | 
|  | if (b == 0x0f) { | 
|  | twobyte = 1; | 
|  | b = insn_fetch(uint8_t, 1, _eip); | 
|  | d = twobyte_table[b]; | 
|  | } | 
|  |  | 
|  | /* Unrecognised? */ | 
|  | if (d == 0) | 
|  | goto cannot_emulate; | 
|  | } | 
|  |  | 
|  | /* ModRM and SIB bytes. */ | 
|  | if (d & ModRM) { | 
|  | modrm = insn_fetch(uint8_t, 1, _eip); | 
|  | modrm_mod |= (modrm & 0xc0) >> 6; | 
|  | modrm_reg |= (modrm & 0x38) >> 3; | 
|  | modrm_rm |= (modrm & 0x07); | 
|  | modrm_ea = 0; | 
|  | use_modrm_ea = 1; | 
|  |  | 
|  | if (modrm_mod == 3) { | 
|  | modrm_val = *(unsigned long *) | 
|  | decode_register(modrm_rm, _regs, d & ByteOp); | 
|  | goto modrm_done; | 
|  | } | 
|  |  | 
|  | if (ad_bytes == 2) { | 
|  | unsigned bx = _regs[VCPU_REGS_RBX]; | 
|  | unsigned bp = _regs[VCPU_REGS_RBP]; | 
|  | unsigned si = _regs[VCPU_REGS_RSI]; | 
|  | unsigned di = _regs[VCPU_REGS_RDI]; | 
|  |  | 
|  | /* 16-bit ModR/M decode. */ | 
|  | switch (modrm_mod) { | 
|  | case 0: | 
|  | if (modrm_rm == 6) | 
|  | modrm_ea += insn_fetch(uint16_t, 2, _eip); | 
|  | break; | 
|  | case 1: | 
|  | modrm_ea += insn_fetch(int8_t, 1, _eip); | 
|  | break; | 
|  | case 2: | 
|  | modrm_ea += insn_fetch(uint16_t, 2, _eip); | 
|  | break; | 
|  | } | 
|  | switch (modrm_rm) { | 
|  | case 0: | 
|  | modrm_ea += bx + si; | 
|  | break; | 
|  | case 1: | 
|  | modrm_ea += bx + di; | 
|  | break; | 
|  | case 2: | 
|  | modrm_ea += bp + si; | 
|  | break; | 
|  | case 3: | 
|  | modrm_ea += bp + di; | 
|  | break; | 
|  | case 4: | 
|  | modrm_ea += si; | 
|  | break; | 
|  | case 5: | 
|  | modrm_ea += di; | 
|  | break; | 
|  | case 6: | 
|  | if (modrm_mod != 0) | 
|  | modrm_ea += bp; | 
|  | break; | 
|  | case 7: | 
|  | modrm_ea += bx; | 
|  | break; | 
|  | } | 
|  | if (modrm_rm == 2 || modrm_rm == 3 || | 
|  | (modrm_rm == 6 && modrm_mod != 0)) | 
|  | if (!override_base) | 
|  | override_base = &ctxt->ss_base; | 
|  | modrm_ea = (uint16_t)modrm_ea; | 
|  | } else { | 
|  | /* 32/64-bit ModR/M decode. */ | 
|  | switch (modrm_rm) { | 
|  | case 4: | 
|  | case 12: | 
|  | sib = insn_fetch(uint8_t, 1, _eip); | 
|  | index_reg |= (sib >> 3) & 7; | 
|  | base_reg |= sib & 7; | 
|  | scale = sib >> 6; | 
|  |  | 
|  | switch (base_reg) { | 
|  | case 5: | 
|  | if (modrm_mod != 0) | 
|  | modrm_ea += _regs[base_reg]; | 
|  | else | 
|  | modrm_ea += insn_fetch(int32_t, 4, _eip); | 
|  | break; | 
|  | default: | 
|  | modrm_ea += _regs[base_reg]; | 
|  | } | 
|  | switch (index_reg) { | 
|  | case 4: | 
|  | break; | 
|  | default: | 
|  | modrm_ea += _regs[index_reg] << scale; | 
|  |  | 
|  | } | 
|  | break; | 
|  | case 5: | 
|  | if (modrm_mod != 0) | 
|  | modrm_ea += _regs[modrm_rm]; | 
|  | else if (mode == X86EMUL_MODE_PROT64) | 
|  | rip_relative = 1; | 
|  | break; | 
|  | default: | 
|  | modrm_ea += _regs[modrm_rm]; | 
|  | break; | 
|  | } | 
|  | switch (modrm_mod) { | 
|  | case 0: | 
|  | if (modrm_rm == 5) | 
|  | modrm_ea += insn_fetch(int32_t, 4, _eip); | 
|  | break; | 
|  | case 1: | 
|  | modrm_ea += insn_fetch(int8_t, 1, _eip); | 
|  | break; | 
|  | case 2: | 
|  | modrm_ea += insn_fetch(int32_t, 4, _eip); | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!override_base) | 
|  | override_base = &ctxt->ds_base; | 
|  | if (mode == X86EMUL_MODE_PROT64 && | 
|  | override_base != &ctxt->fs_base && | 
|  | override_base != &ctxt->gs_base) | 
|  | override_base = 0; | 
|  |  | 
|  | if (override_base) | 
|  | modrm_ea += *override_base; | 
|  |  | 
|  | if (rip_relative) { | 
|  | modrm_ea += _eip; | 
|  | switch (d & SrcMask) { | 
|  | case SrcImmByte: | 
|  | modrm_ea += 1; | 
|  | break; | 
|  | case SrcImm: | 
|  | if (d & ByteOp) | 
|  | modrm_ea += 1; | 
|  | else | 
|  | if (op_bytes == 8) | 
|  | modrm_ea += 4; | 
|  | else | 
|  | modrm_ea += op_bytes; | 
|  | } | 
|  | } | 
|  | if (ad_bytes != 8) | 
|  | modrm_ea = (uint32_t)modrm_ea; | 
|  | cr2 = modrm_ea; | 
|  | modrm_done: | 
|  | ; | 
|  | } | 
|  |  | 
|  | /* Decode and fetch the destination operand: register or memory. */ | 
|  | switch (d & DstMask) { | 
|  | case ImplicitOps: | 
|  | /* Special instructions do their own operand decoding. */ | 
|  | goto special_insn; | 
|  | case DstReg: | 
|  | dst.type = OP_REG; | 
|  | if ((d & ByteOp) | 
|  | && !(twobyte && (b == 0xb6 || b == 0xb7))) { | 
|  | dst.ptr = decode_register(modrm_reg, _regs, | 
|  | (rex_prefix == 0)); | 
|  | dst.val = *(uint8_t *) dst.ptr; | 
|  | dst.bytes = 1; | 
|  | } else { | 
|  | dst.ptr = decode_register(modrm_reg, _regs, 0); | 
|  | switch ((dst.bytes = op_bytes)) { | 
|  | case 2: | 
|  | dst.val = *(uint16_t *)dst.ptr; | 
|  | break; | 
|  | case 4: | 
|  | dst.val = *(uint32_t *)dst.ptr; | 
|  | break; | 
|  | case 8: | 
|  | dst.val = *(uint64_t *)dst.ptr; | 
|  | break; | 
|  | } | 
|  | } | 
|  | break; | 
|  | case DstMem: | 
|  | dst.type = OP_MEM; | 
|  | dst.ptr = (unsigned long *)cr2; | 
|  | dst.bytes = (d & ByteOp) ? 1 : op_bytes; | 
|  | if (!(d & Mov) && /* optimisation - avoid slow emulated read */ | 
|  | ((rc = ops->read_emulated((unsigned long)dst.ptr, | 
|  | &dst.val, dst.bytes, ctxt)) != 0)) | 
|  | goto done; | 
|  | break; | 
|  | } | 
|  | dst.orig_val = dst.val; | 
|  |  | 
|  | /* | 
|  | * Decode and fetch the source operand: register, memory | 
|  | * or immediate. | 
|  | */ | 
|  | switch (d & SrcMask) { | 
|  | case SrcNone: | 
|  | break; | 
|  | case SrcReg: | 
|  | src.type = OP_REG; | 
|  | if (d & ByteOp) { | 
|  | src.ptr = decode_register(modrm_reg, _regs, | 
|  | (rex_prefix == 0)); | 
|  | src.val = src.orig_val = *(uint8_t *) src.ptr; | 
|  | src.bytes = 1; | 
|  | } else { | 
|  | src.ptr = decode_register(modrm_reg, _regs, 0); | 
|  | switch ((src.bytes = op_bytes)) { | 
|  | case 2: | 
|  | src.val = src.orig_val = *(uint16_t *) src.ptr; | 
|  | break; | 
|  | case 4: | 
|  | src.val = src.orig_val = *(uint32_t *) src.ptr; | 
|  | break; | 
|  | case 8: | 
|  | src.val = src.orig_val = *(uint64_t *) src.ptr; | 
|  | break; | 
|  | } | 
|  | } | 
|  | break; | 
|  | case SrcMem16: | 
|  | src.bytes = 2; | 
|  | goto srcmem_common; | 
|  | case SrcMem32: | 
|  | src.bytes = 4; | 
|  | goto srcmem_common; | 
|  | case SrcMem: | 
|  | src.bytes = (d & ByteOp) ? 1 : op_bytes; | 
|  | srcmem_common: | 
|  | src.type = OP_MEM; | 
|  | src.ptr = (unsigned long *)cr2; | 
|  | if ((rc = ops->read_emulated((unsigned long)src.ptr, | 
|  | &src.val, src.bytes, ctxt)) != 0) | 
|  | goto done; | 
|  | src.orig_val = src.val; | 
|  | break; | 
|  | case SrcImm: | 
|  | src.type = OP_IMM; | 
|  | src.ptr = (unsigned long *)_eip; | 
|  | src.bytes = (d & ByteOp) ? 1 : op_bytes; | 
|  | if (src.bytes == 8) | 
|  | src.bytes = 4; | 
|  | /* NB. Immediates are sign-extended as necessary. */ | 
|  | switch (src.bytes) { | 
|  | case 1: | 
|  | src.val = insn_fetch(int8_t, 1, _eip); | 
|  | break; | 
|  | case 2: | 
|  | src.val = insn_fetch(int16_t, 2, _eip); | 
|  | break; | 
|  | case 4: | 
|  | src.val = insn_fetch(int32_t, 4, _eip); | 
|  | break; | 
|  | } | 
|  | break; | 
|  | case SrcImmByte: | 
|  | src.type = OP_IMM; | 
|  | src.ptr = (unsigned long *)_eip; | 
|  | src.bytes = 1; | 
|  | src.val = insn_fetch(int8_t, 1, _eip); | 
|  | break; | 
|  | } | 
|  |  | 
|  | if (twobyte) | 
|  | goto twobyte_insn; | 
|  |  | 
|  | switch (b) { | 
|  | case 0x00 ... 0x05: | 
|  | add:		/* add */ | 
|  | emulate_2op_SrcV("add", src, dst, _eflags); | 
|  | break; | 
|  | case 0x08 ... 0x0d: | 
|  | or:		/* or */ | 
|  | emulate_2op_SrcV("or", src, dst, _eflags); | 
|  | break; | 
|  | case 0x10 ... 0x15: | 
|  | adc:		/* adc */ | 
|  | emulate_2op_SrcV("adc", src, dst, _eflags); | 
|  | break; | 
|  | case 0x18 ... 0x1d: | 
|  | sbb:		/* sbb */ | 
|  | emulate_2op_SrcV("sbb", src, dst, _eflags); | 
|  | break; | 
|  | case 0x20 ... 0x25: | 
|  | and:		/* and */ | 
|  | emulate_2op_SrcV("and", src, dst, _eflags); | 
|  | break; | 
|  | case 0x28 ... 0x2d: | 
|  | sub:		/* sub */ | 
|  | emulate_2op_SrcV("sub", src, dst, _eflags); | 
|  | break; | 
|  | case 0x30 ... 0x35: | 
|  | xor:		/* xor */ | 
|  | emulate_2op_SrcV("xor", src, dst, _eflags); | 
|  | break; | 
|  | case 0x38 ... 0x3d: | 
|  | cmp:		/* cmp */ | 
|  | emulate_2op_SrcV("cmp", src, dst, _eflags); | 
|  | break; | 
|  | case 0x63:		/* movsxd */ | 
|  | if (mode != X86EMUL_MODE_PROT64) | 
|  | goto cannot_emulate; | 
|  | dst.val = (int32_t) src.val; | 
|  | break; | 
|  | case 0x80 ... 0x83:	/* Grp1 */ | 
|  | switch (modrm_reg) { | 
|  | case 0: | 
|  | goto add; | 
|  | case 1: | 
|  | goto or; | 
|  | case 2: | 
|  | goto adc; | 
|  | case 3: | 
|  | goto sbb; | 
|  | case 4: | 
|  | goto and; | 
|  | case 5: | 
|  | goto sub; | 
|  | case 6: | 
|  | goto xor; | 
|  | case 7: | 
|  | goto cmp; | 
|  | } | 
|  | break; | 
|  | case 0x84 ... 0x85: | 
|  | test:		/* test */ | 
|  | emulate_2op_SrcV("test", src, dst, _eflags); | 
|  | break; | 
|  | case 0x86 ... 0x87:	/* xchg */ | 
|  | /* Write back the register source. */ | 
|  | switch (dst.bytes) { | 
|  | case 1: | 
|  | *(uint8_t *) src.ptr = (uint8_t) dst.val; | 
|  | break; | 
|  | case 2: | 
|  | *(uint16_t *) src.ptr = (uint16_t) dst.val; | 
|  | break; | 
|  | case 4: | 
|  | *src.ptr = (uint32_t) dst.val; | 
|  | break;	/* 64b reg: zero-extend */ | 
|  | case 8: | 
|  | *src.ptr = dst.val; | 
|  | break; | 
|  | } | 
|  | /* | 
|  | * Write back the memory destination with implicit LOCK | 
|  | * prefix. | 
|  | */ | 
|  | dst.val = src.val; | 
|  | lock_prefix = 1; | 
|  | break; | 
|  | case 0xa0 ... 0xa1:	/* mov */ | 
|  | dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX]; | 
|  | dst.val = src.val; | 
|  | _eip += ad_bytes;	/* skip src displacement */ | 
|  | break; | 
|  | case 0xa2 ... 0xa3:	/* mov */ | 
|  | dst.val = (unsigned long)_regs[VCPU_REGS_RAX]; | 
|  | _eip += ad_bytes;	/* skip dst displacement */ | 
|  | break; | 
|  | case 0x88 ... 0x8b:	/* mov */ | 
|  | case 0xc6 ... 0xc7:	/* mov (sole member of Grp11) */ | 
|  | dst.val = src.val; | 
|  | break; | 
|  | case 0x8f:		/* pop (sole member of Grp1a) */ | 
|  | /* 64-bit mode: POP always pops a 64-bit operand. */ | 
|  | if (mode == X86EMUL_MODE_PROT64) | 
|  | dst.bytes = 8; | 
|  | if ((rc = ops->read_std(register_address(ctxt->ss_base, | 
|  | _regs[VCPU_REGS_RSP]), | 
|  | &dst.val, dst.bytes, ctxt)) != 0) | 
|  | goto done; | 
|  | register_address_increment(_regs[VCPU_REGS_RSP], dst.bytes); | 
|  | break; | 
|  | case 0xc0 ... 0xc1: | 
|  | grp2:		/* Grp2 */ | 
|  | switch (modrm_reg) { | 
|  | case 0:	/* rol */ | 
|  | emulate_2op_SrcB("rol", src, dst, _eflags); | 
|  | break; | 
|  | case 1:	/* ror */ | 
|  | emulate_2op_SrcB("ror", src, dst, _eflags); | 
|  | break; | 
|  | case 2:	/* rcl */ | 
|  | emulate_2op_SrcB("rcl", src, dst, _eflags); | 
|  | break; | 
|  | case 3:	/* rcr */ | 
|  | emulate_2op_SrcB("rcr", src, dst, _eflags); | 
|  | break; | 
|  | case 4:	/* sal/shl */ | 
|  | case 6:	/* sal/shl */ | 
|  | emulate_2op_SrcB("sal", src, dst, _eflags); | 
|  | break; | 
|  | case 5:	/* shr */ | 
|  | emulate_2op_SrcB("shr", src, dst, _eflags); | 
|  | break; | 
|  | case 7:	/* sar */ | 
|  | emulate_2op_SrcB("sar", src, dst, _eflags); | 
|  | break; | 
|  | } | 
|  | break; | 
|  | case 0xd0 ... 0xd1:	/* Grp2 */ | 
|  | src.val = 1; | 
|  | goto grp2; | 
|  | case 0xd2 ... 0xd3:	/* Grp2 */ | 
|  | src.val = _regs[VCPU_REGS_RCX]; | 
|  | goto grp2; | 
|  | case 0xf6 ... 0xf7:	/* Grp3 */ | 
|  | switch (modrm_reg) { | 
|  | case 0 ... 1:	/* test */ | 
|  | /* | 
|  | * Special case in Grp3: test has an immediate | 
|  | * source operand. | 
|  | */ | 
|  | src.type = OP_IMM; | 
|  | src.ptr = (unsigned long *)_eip; | 
|  | src.bytes = (d & ByteOp) ? 1 : op_bytes; | 
|  | if (src.bytes == 8) | 
|  | src.bytes = 4; | 
|  | switch (src.bytes) { | 
|  | case 1: | 
|  | src.val = insn_fetch(int8_t, 1, _eip); | 
|  | break; | 
|  | case 2: | 
|  | src.val = insn_fetch(int16_t, 2, _eip); | 
|  | break; | 
|  | case 4: | 
|  | src.val = insn_fetch(int32_t, 4, _eip); | 
|  | break; | 
|  | } | 
|  | goto test; | 
|  | case 2:	/* not */ | 
|  | dst.val = ~dst.val; | 
|  | break; | 
|  | case 3:	/* neg */ | 
|  | emulate_1op("neg", dst, _eflags); | 
|  | break; | 
|  | default: | 
|  | goto cannot_emulate; | 
|  | } | 
|  | break; | 
|  | case 0xfe ... 0xff:	/* Grp4/Grp5 */ | 
|  | switch (modrm_reg) { | 
|  | case 0:	/* inc */ | 
|  | emulate_1op("inc", dst, _eflags); | 
|  | break; | 
|  | case 1:	/* dec */ | 
|  | emulate_1op("dec", dst, _eflags); | 
|  | break; | 
|  | case 6:	/* push */ | 
|  | /* 64-bit mode: PUSH always pushes a 64-bit operand. */ | 
|  | if (mode == X86EMUL_MODE_PROT64) { | 
|  | dst.bytes = 8; | 
|  | if ((rc = ops->read_std((unsigned long)dst.ptr, | 
|  | &dst.val, 8, | 
|  | ctxt)) != 0) | 
|  | goto done; | 
|  | } | 
|  | register_address_increment(_regs[VCPU_REGS_RSP], | 
|  | -dst.bytes); | 
|  | if ((rc = ops->write_std( | 
|  | register_address(ctxt->ss_base, | 
|  | _regs[VCPU_REGS_RSP]), | 
|  | dst.val, dst.bytes, ctxt)) != 0) | 
|  | goto done; | 
|  | dst.val = dst.orig_val;	/* skanky: disable writeback */ | 
|  | break; | 
|  | default: | 
|  | goto cannot_emulate; | 
|  | } | 
|  | break; | 
|  | } | 
|  |  | 
|  | writeback: | 
|  | if ((d & Mov) || (dst.orig_val != dst.val)) { | 
|  | switch (dst.type) { | 
|  | case OP_REG: | 
|  | /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */ | 
|  | switch (dst.bytes) { | 
|  | case 1: | 
|  | *(uint8_t *)dst.ptr = (uint8_t)dst.val; | 
|  | break; | 
|  | case 2: | 
|  | *(uint16_t *)dst.ptr = (uint16_t)dst.val; | 
|  | break; | 
|  | case 4: | 
|  | *dst.ptr = (uint32_t)dst.val; | 
|  | break;	/* 64b: zero-ext */ | 
|  | case 8: | 
|  | *dst.ptr = dst.val; | 
|  | break; | 
|  | } | 
|  | break; | 
|  | case OP_MEM: | 
|  | if (lock_prefix) | 
|  | rc = ops->cmpxchg_emulated((unsigned long)dst. | 
|  | ptr, dst.orig_val, | 
|  | dst.val, dst.bytes, | 
|  | ctxt); | 
|  | else | 
|  | rc = ops->write_emulated((unsigned long)dst.ptr, | 
|  | dst.val, dst.bytes, | 
|  | ctxt); | 
|  | if (rc != 0) | 
|  | goto done; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Commit shadow register state. */ | 
|  | memcpy(ctxt->vcpu->regs, _regs, sizeof _regs); | 
|  | ctxt->eflags = _eflags; | 
|  | ctxt->vcpu->rip = _eip; | 
|  |  | 
|  | done: | 
|  | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; | 
|  |  | 
|  | special_insn: | 
|  | if (twobyte) | 
|  | goto twobyte_special_insn; | 
|  | if (rep_prefix) { | 
|  | if (_regs[VCPU_REGS_RCX] == 0) { | 
|  | ctxt->vcpu->rip = _eip; | 
|  | goto done; | 
|  | } | 
|  | _regs[VCPU_REGS_RCX]--; | 
|  | _eip = ctxt->vcpu->rip; | 
|  | } | 
|  | switch (b) { | 
|  | case 0xa4 ... 0xa5:	/* movs */ | 
|  | dst.type = OP_MEM; | 
|  | dst.bytes = (d & ByteOp) ? 1 : op_bytes; | 
|  | dst.ptr = (unsigned long *)register_address(ctxt->es_base, | 
|  | _regs[VCPU_REGS_RDI]); | 
|  | if ((rc = ops->read_emulated(register_address( | 
|  | override_base ? *override_base : ctxt->ds_base, | 
|  | _regs[VCPU_REGS_RSI]), &dst.val, dst.bytes, ctxt)) != 0) | 
|  | goto done; | 
|  | register_address_increment(_regs[VCPU_REGS_RSI], | 
|  | (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); | 
|  | register_address_increment(_regs[VCPU_REGS_RDI], | 
|  | (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); | 
|  | break; | 
|  | case 0xa6 ... 0xa7:	/* cmps */ | 
|  | DPRINTF("Urk! I don't handle CMPS.\n"); | 
|  | goto cannot_emulate; | 
|  | case 0xaa ... 0xab:	/* stos */ | 
|  | dst.type = OP_MEM; | 
|  | dst.bytes = (d & ByteOp) ? 1 : op_bytes; | 
|  | dst.ptr = (unsigned long *)cr2; | 
|  | dst.val = _regs[VCPU_REGS_RAX]; | 
|  | register_address_increment(_regs[VCPU_REGS_RDI], | 
|  | (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); | 
|  | break; | 
|  | case 0xac ... 0xad:	/* lods */ | 
|  | dst.type = OP_REG; | 
|  | dst.bytes = (d & ByteOp) ? 1 : op_bytes; | 
|  | dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX]; | 
|  | if ((rc = ops->read_emulated(cr2, &dst.val, dst.bytes, ctxt)) != 0) | 
|  | goto done; | 
|  | register_address_increment(_regs[VCPU_REGS_RSI], | 
|  | (_eflags & EFLG_DF) ? -dst.bytes : dst.bytes); | 
|  | break; | 
|  | case 0xae ... 0xaf:	/* scas */ | 
|  | DPRINTF("Urk! I don't handle SCAS.\n"); | 
|  | goto cannot_emulate; | 
|  | } | 
|  | goto writeback; | 
|  |  | 
|  | twobyte_insn: | 
|  | switch (b) { | 
|  | case 0x01: /* lgdt, lidt, lmsw */ | 
|  | switch (modrm_reg) { | 
|  | uint16_t size; | 
|  | unsigned long address; | 
|  |  | 
|  | case 2: /* lgdt */ | 
|  | rc = read_descriptor(ctxt, ops, src.ptr, | 
|  | &size, &address, op_bytes); | 
|  | if (rc) | 
|  | goto done; | 
|  | #warning "implement realmode_lgdt" | 
|  | //realmode_lgdt(ctxt->vcpu, size, address); | 
|  | break; | 
|  | case 3: /* lidt */ | 
|  | rc = read_descriptor(ctxt, ops, src.ptr, | 
|  | &size, &address, op_bytes); | 
|  | if (rc) | 
|  | goto done; | 
|  | #warning "implement realmode_lidt" | 
|  | //realmode_lidt(ctxt->vcpu, size, address); | 
|  | break; | 
|  | case 6: /* lmsw */ | 
|  | #warning "implement realmod_lmsw" | 
|  | //realmode_lmsw(ctxt->vcpu, (uint16_t)modrm_val, &_eflags); | 
|  | break; | 
|  | default: | 
|  | goto cannot_emulate; | 
|  | } | 
|  | break; | 
|  | case 0x40 ... 0x4f:	/* cmov */ | 
|  | dst.val = dst.orig_val = src.val; | 
|  | d &= ~Mov;	/* default to no move */ | 
|  | /* | 
|  | * First, assume we're decoding an even cmov opcode | 
|  | * (lsb == 0). | 
|  | */ | 
|  | switch ((b & 15) >> 1) { | 
|  | case 0:	/* cmovo */ | 
|  | d |= (_eflags & EFLG_OF) ? Mov : 0; | 
|  | break; | 
|  | case 1:	/* cmovb/cmovc/cmovnae */ | 
|  | d |= (_eflags & EFLG_CF) ? Mov : 0; | 
|  | break; | 
|  | case 2:	/* cmovz/cmove */ | 
|  | d |= (_eflags & EFLG_ZF) ? Mov : 0; | 
|  | break; | 
|  | case 3:	/* cmovbe/cmovna */ | 
|  | d |= (_eflags & (EFLG_CF | EFLG_ZF)) ? Mov : 0; | 
|  | break; | 
|  | case 4:	/* cmovs */ | 
|  | d |= (_eflags & EFLG_SF) ? Mov : 0; | 
|  | break; | 
|  | case 5:	/* cmovp/cmovpe */ | 
|  | d |= (_eflags & EFLG_PF) ? Mov : 0; | 
|  | break; | 
|  | case 7:	/* cmovle/cmovng */ | 
|  | d |= (_eflags & EFLG_ZF) ? Mov : 0; | 
|  | /* fall through */ | 
|  | case 6:	/* cmovl/cmovnge */ | 
|  | d |= (!(_eflags & EFLG_SF) != | 
|  | !(_eflags & EFLG_OF)) ? Mov : 0; | 
|  | break; | 
|  | } | 
|  | /* Odd cmov opcodes (lsb == 1) have inverted sense. */ | 
|  | d ^= (b & 1) ? Mov : 0; | 
|  | break; | 
|  | case 0xb0 ... 0xb1:	/* cmpxchg */ | 
|  | /* | 
|  | * Save real source value, then compare EAX against | 
|  | * destination. | 
|  | */ | 
|  | src.orig_val = src.val; | 
|  | src.val = _regs[VCPU_REGS_RAX]; | 
|  | emulate_2op_SrcV("cmp", src, dst, _eflags); | 
|  | /* Always write back. The question is: where to? */ | 
|  | d |= Mov; | 
|  | if (_eflags & EFLG_ZF) { | 
|  | /* Success: write back to memory. */ | 
|  | dst.val = src.orig_val; | 
|  | } else { | 
|  | /* Failure: write the value we saw to EAX. */ | 
|  | dst.type = OP_REG; | 
|  | dst.ptr = (unsigned long *)&_regs[VCPU_REGS_RAX]; | 
|  | } | 
|  | break; | 
|  | case 0xa3: | 
|  | bt:		/* bt */ | 
|  | src.val &= (dst.bytes << 3) - 1; /* only subword offset */ | 
|  | emulate_2op_SrcV_nobyte("bt", src, dst, _eflags); | 
|  | break; | 
|  | case 0xb3: | 
|  | btr:		/* btr */ | 
|  | src.val &= (dst.bytes << 3) - 1; /* only subword offset */ | 
|  | emulate_2op_SrcV_nobyte("btr", src, dst, _eflags); | 
|  | break; | 
|  | case 0xab: | 
|  | bts:		/* bts */ | 
|  | src.val &= (dst.bytes << 3) - 1; /* only subword offset */ | 
|  | emulate_2op_SrcV_nobyte("bts", src, dst, _eflags); | 
|  | break; | 
|  | case 0xb6 ... 0xb7:	/* movzx */ | 
|  | dst.bytes = op_bytes; | 
|  | dst.val = (d & ByteOp) ? (uint8_t) src.val : (uint16_t) src.val; | 
|  | break; | 
|  | case 0xbb: | 
|  | btc:		/* btc */ | 
|  | src.val &= (dst.bytes << 3) - 1; /* only subword offset */ | 
|  | emulate_2op_SrcV_nobyte("btc", src, dst, _eflags); | 
|  | break; | 
|  | case 0xba:		/* Grp8 */ | 
|  | switch (modrm_reg & 3) { | 
|  | case 0: | 
|  | goto bt; | 
|  | case 1: | 
|  | goto bts; | 
|  | case 2: | 
|  | goto btr; | 
|  | case 3: | 
|  | goto btc; | 
|  | } | 
|  | break; | 
|  | case 0xbe ... 0xbf:	/* movsx */ | 
|  | dst.bytes = op_bytes; | 
|  | dst.val = (d & ByteOp) ? (int8_t) src.val : (int16_t) src.val; | 
|  | break; | 
|  | } | 
|  | goto writeback; | 
|  |  | 
|  | twobyte_special_insn: | 
|  | /* Disable writeback. */ | 
|  | dst.orig_val = dst.val; | 
|  | switch (b) { | 
|  | case 0x0d:		/* GrpP (prefetch) */ | 
|  | case 0x18:		/* Grp16 (prefetch/nop) */ | 
|  | break; | 
|  | case 0x20: /* mov cr, reg */ | 
|  | b = insn_fetch(uint8_t, 1, _eip); | 
|  | if ((b & 0xc0) != 0xc0) | 
|  | goto cannot_emulate; | 
|  | #warning "implement realmode_get_cr" | 
|  | //_regs[(b >> 3) & 7] = realmode_get_cr(ctxt->vcpu, b & 7); | 
|  | break; | 
|  | case 0x22: /* mov reg, cr */ | 
|  | b = insn_fetch(uint8_t, 1, _eip); | 
|  | if ((b & 0xc0) != 0xc0) | 
|  | goto cannot_emulate; | 
|  | #warning "implement realmod_set_cr" | 
|  | //realmode_set_cr(ctxt->vcpu, b & 7, _regs[(b >> 3) & 7] & -1u, | 
|  | //		&_eflags); | 
|  | break; | 
|  | case 0xc7:		/* Grp9 (cmpxchg8b) */ | 
|  | #if defined(__i386__) | 
|  | { | 
|  | unsigned long old_lo, old_hi; | 
|  | if (((rc = ops->read_emulated(cr2 + 0, &old_lo, 4, | 
|  | ctxt)) != 0) | 
|  | || ((rc = ops->read_emulated(cr2 + 4, &old_hi, 4, | 
|  | ctxt)) != 0)) | 
|  | goto done; | 
|  | if ((old_lo != _regs[VCPU_REGS_RAX]) | 
|  | || (old_hi != _regs[VCPU_REGS_RDI])) { | 
|  | _regs[VCPU_REGS_RAX] = old_lo; | 
|  | _regs[VCPU_REGS_RDX] = old_hi; | 
|  | _eflags &= ~EFLG_ZF; | 
|  | } else if (ops->cmpxchg8b_emulated == NULL) { | 
|  | rc = X86EMUL_UNHANDLEABLE; | 
|  | goto done; | 
|  | } else { | 
|  | if ((rc = ops->cmpxchg8b_emulated(cr2, old_lo, | 
|  | old_hi, | 
|  | _regs[VCPU_REGS_RBX], | 
|  | _regs[VCPU_REGS_RCX], | 
|  | ctxt)) != 0) | 
|  | goto done; | 
|  | _eflags |= EFLG_ZF; | 
|  | } | 
|  | break; | 
|  | } | 
|  | #elif defined(__x86_64__) | 
|  | { | 
|  | unsigned long old, new; | 
|  | if ((rc = ops->read_emulated(cr2, &old, 8, ctxt)) != 0) | 
|  | goto done; | 
|  | if (((uint32_t) (old >> 0) != (uint32_t) _regs[VCPU_REGS_RAX]) || | 
|  | ((uint32_t) (old >> 32) != (uint32_t) _regs[VCPU_REGS_RDX])) { | 
|  | _regs[VCPU_REGS_RAX] = (uint32_t) (old >> 0); | 
|  | _regs[VCPU_REGS_RDX] = (uint32_t) (old >> 32); | 
|  | _eflags &= ~EFLG_ZF; | 
|  | } else { | 
|  | new = (_regs[VCPU_REGS_RCX] << 32) | (uint32_t) _regs[VCPU_REGS_RBX]; | 
|  | if ((rc = ops->cmpxchg_emulated(cr2, old, | 
|  | new, 8, ctxt)) != 0) | 
|  | goto done; | 
|  | _eflags |= EFLG_ZF; | 
|  | } | 
|  | break; | 
|  | } | 
|  | #endif | 
|  | } | 
|  | goto writeback; | 
|  |  | 
|  | cannot_emulate: | 
|  | printd("Cannot emulate %02x\n", b); | 
|  | return -1; | 
|  | } | 
|  |  |