KVM: x86 emulator: add macros for executing instructions that may trap
authorAvi Kivity <avi@redhat.com>
Thu, 26 Aug 2010 08:59:00 +0000 (11:59 +0300)
committerAvi Kivity <avi@redhat.com>
Sun, 24 Oct 2010 08:51:41 +0000 (10:51 +0200)
Like DIV and IDIV.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
arch/x86/kvm/emulate.c

index 58e715cb5172423c5997f38f84108caa3d5d96db..e96cce170228cd7f0dcf7836c5d35f722165b1d9 100644 (file)
@@ -331,6 +331,27 @@ struct group_dual {
                          "a" (_rax), "d" (_rdx));                      \
        } while (0)
 
+#define __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, _eflags, _suffix, _ex) \
+       do {                                                            \
+               unsigned long _tmp;                                     \
+                                                                       \
+               __asm__ __volatile__ (                                  \
+                       _PRE_EFLAGS("0", "5", "1")                      \
+                       "1: \n\t"                                       \
+                       _op _suffix " %6; "                             \
+                       "2: \n\t"                                       \
+                       _POST_EFLAGS("0", "5", "1")                     \
+                       ".pushsection .fixup,\"ax\" \n\t"               \
+                       "3: movb $1, %4 \n\t"                           \
+                       "jmp 2b \n\t"                                   \
+                       ".popsection \n\t"                              \
+                       _ASM_EXTABLE(1b, 3b)                            \
+                       : "=m" (_eflags), "=&r" (_tmp),                 \
+                         "+a" (_rax), "+d" (_rdx), "+qm"(_ex)          \
+                       : "i" (EFLAGS_MASK), "m" ((_src).val),          \
+                         "a" (_rax), "d" (_rdx));                      \
+       } while (0)
+
 /* instruction has only one source operand, destination is implicit (e.g. mul, div, imul, idiv) */
 #define emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags)                    \
        do {                                                                    \
@@ -342,6 +363,28 @@ struct group_dual {
                }                                                       \
        } while (0)
 
+#define emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, _eflags, _ex)    \
+       do {                                                            \
+               switch((_src).bytes) {                                  \
+               case 1:                                                 \
+                       __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
+                                                _eflags, "b", _ex);    \
+                       break;                                          \
+               case 2:                                                 \
+                       __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
+                                                _eflags, "w", _ex);    \
+                       break;                                          \
+               case 4:                                                 \
+                       __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
+                                                _eflags, "l", _ex);    \
+                       break;                                          \
+               case 8: ON64(                                           \
+                       __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
+                                                _eflags, "q", _ex));   \
+                       break;                                          \
+               }                                                       \
+       } while (0)
+
 /* Fetch next part of the instruction being emulated. */
 #define insn_fetch(_type, _size, _eip)                                  \
 ({     unsigned long _x;                                               \