diff options
author | Avi Kivity <avi@redhat.com> | 2008-11-26 08:30:45 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2008-12-31 09:55:03 -0500 |
commit | 6b7ad61ffb9ca110add6f7fb36cc8a4dd89696a4 (patch) | |
tree | 21c1aa0a976dec1ea46410184cd2131aa13c8158 /arch/x86/kvm/x86_emulate.c | |
parent | dda96d8f1b3de692cce09969ce28fe22e58e5acf (diff) |
KVM: x86 emulator: consolidate emulation of two operand instructions
No need to repeat the same assembly block over and over.
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86_emulate.c')
-rw-r--r-- | arch/x86/kvm/x86_emulate.c | 79 |
1 files changed, 28 insertions, 51 deletions
diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index 5f87d3e59195..a11af6f74d68 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c | |||
@@ -365,49 +365,42 @@ static u16 group2_table[] = { | |||
365 | #define ON64(x) | 365 | #define ON64(x) |
366 | #endif | 366 | #endif |
367 | 367 | ||
368 | #define ____emulate_2op(_op, _src, _dst, _eflags, _x, _y, _suffix) \ | ||
369 | do { \ | ||
370 | __asm__ __volatile__ ( \ | ||
371 | _PRE_EFLAGS("0", "4", "2") \ | ||
372 | _op _suffix " %"_x"3,%1; " \ | ||
373 | _POST_EFLAGS("0", "4", "2") \ | ||
374 | : "=m" (_eflags), "=m" ((_dst).val), \ | ||
375 | "=&r" (_tmp) \ | ||
376 | : _y ((_src).val), "i" (EFLAGS_MASK)); \ | ||
377 | } while (0); | ||
378 | |||
379 | |||
368 | /* Raw emulation: instruction has two explicit operands. */ | 380 | /* Raw emulation: instruction has two explicit operands. */ |
369 | #define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \ | 381 | #define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \ |
370 | do { \ | 382 | do { \ |
371 | unsigned long _tmp; \ | 383 | unsigned long _tmp; \ |
372 | \ | 384 | \ |
373 | switch ((_dst).bytes) { \ | 385 | switch ((_dst).bytes) { \ |
374 | case 2: \ | 386 | case 2: \ |
375 | __asm__ __volatile__ ( \ | 387 | ____emulate_2op(_op,_src,_dst,_eflags,_wx,_wy,"w"); \ |
376 | _PRE_EFLAGS("0", "4", "2") \ | 388 | break; \ |
377 | _op"w %"_wx"3,%1; " \ | 389 | case 4: \ |
378 | _POST_EFLAGS("0", "4", "2") \ | 390 | ____emulate_2op(_op,_src,_dst,_eflags,_lx,_ly,"l"); \ |
379 | : "=m" (_eflags), "=m" ((_dst).val), \ | 391 | break; \ |
380 | "=&r" (_tmp) \ | 392 | case 8: \ |
381 | : _wy ((_src).val), "i" (EFLAGS_MASK)); \ | 393 | ON64(____emulate_2op(_op,_src,_dst,_eflags,_qx,_qy,"q")); \ |
382 | break; \ | 394 | break; \ |
383 | case 4: \ | 395 | } \ |
384 | __asm__ __volatile__ ( \ | ||
385 | _PRE_EFLAGS("0", "4", "2") \ | ||
386 | _op"l %"_lx"3,%1; " \ | ||
387 | _POST_EFLAGS("0", "4", "2") \ | ||
388 | : "=m" (_eflags), "=m" ((_dst).val), \ | ||
389 | "=&r" (_tmp) \ | ||
390 | : _ly ((_src).val), "i" (EFLAGS_MASK)); \ | ||
391 | break; \ | ||
392 | case 8: \ | ||
393 | __emulate_2op_8byte(_op, _src, _dst, \ | ||
394 | _eflags, _qx, _qy); \ | ||
395 | break; \ | ||
396 | } \ | ||
397 | } while (0) | 396 | } while (0) |
398 | 397 | ||
399 | #define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \ | 398 | #define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \ |
400 | do { \ | 399 | do { \ |
401 | unsigned long __tmp; \ | 400 | unsigned long _tmp; \ |
402 | switch ((_dst).bytes) { \ | 401 | switch ((_dst).bytes) { \ |
403 | case 1: \ | 402 | case 1: \ |
404 | __asm__ __volatile__ ( \ | 403 | ____emulate_2op(_op,_src,_dst,_eflags,_bx,_by,"b"); \ |
405 | _PRE_EFLAGS("0", "4", "2") \ | ||
406 | _op"b %"_bx"3,%1; " \ | ||
407 | _POST_EFLAGS("0", "4", "2") \ | ||
408 | : "=m" (_eflags), "=m" ((_dst).val), \ | ||
409 | "=&r" (__tmp) \ | ||
410 | : _by ((_src).val), "i" (EFLAGS_MASK)); \ | ||
411 | break; \ | 404 | break; \ |
412 | default: \ | 405 | default: \ |
413 | __emulate_2op_nobyte(_op, _src, _dst, _eflags, \ | 406 | __emulate_2op_nobyte(_op, _src, _dst, _eflags, \ |
@@ -455,22 +448,6 @@ static u16 group2_table[] = { | |||
455 | } \ | 448 | } \ |
456 | } while (0) | 449 | } while (0) |
457 | 450 | ||
458 | /* Emulate an instruction with quadword operands (x86/64 only). */ | ||
459 | #if defined(CONFIG_X86_64) | ||
460 | #define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy) \ | ||
461 | do { \ | ||
462 | __asm__ __volatile__ ( \ | ||
463 | _PRE_EFLAGS("0", "4", "2") \ | ||
464 | _op"q %"_qx"3,%1; " \ | ||
465 | _POST_EFLAGS("0", "4", "2") \ | ||
466 | : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ | ||
467 | : _qy ((_src).val), "i" (EFLAGS_MASK)); \ | ||
468 | } while (0) | ||
469 | |||
470 | #elif defined(__i386__) | ||
471 | #define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy) | ||
472 | #endif /* __i386__ */ | ||
473 | |||
474 | /* Fetch next part of the instruction being emulated. */ | 451 | /* Fetch next part of the instruction being emulated. */ |
475 | #define insn_fetch(_type, _size, _eip) \ | 452 | #define insn_fetch(_type, _size, _eip) \ |
476 | ({ unsigned long _x; \ | 453 | ({ unsigned long _x; \ |