diff options
-rw-r--r-- | arch/x86/kvm/emulate.c | 60 |
1 files changed, 29 insertions, 31 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index a94b1d76f799..e13138dd073e 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -499,6 +499,28 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt) | |||
499 | ON64(FOP3E(op##q, rax, rbx, cl)) \ | 499 | ON64(FOP3E(op##q, rax, rbx, cl)) \ |
500 | FOP_END | 500 | FOP_END |
501 | 501 | ||
502 | /* Special case for SETcc - 1 instruction per cc */ | ||
503 | #define FOP_SETCC(op) ".align 4; " #op " %al; ret \n\t" | ||
504 | |||
505 | FOP_START(setcc) | ||
506 | FOP_SETCC(seto) | ||
507 | FOP_SETCC(setno) | ||
508 | FOP_SETCC(setc) | ||
509 | FOP_SETCC(setnc) | ||
510 | FOP_SETCC(setz) | ||
511 | FOP_SETCC(setnz) | ||
512 | FOP_SETCC(setbe) | ||
513 | FOP_SETCC(setnbe) | ||
514 | FOP_SETCC(sets) | ||
515 | FOP_SETCC(setns) | ||
516 | FOP_SETCC(setp) | ||
517 | FOP_SETCC(setnp) | ||
518 | FOP_SETCC(setl) | ||
519 | FOP_SETCC(setnl) | ||
520 | FOP_SETCC(setle) | ||
521 | FOP_SETCC(setnle) | ||
522 | FOP_END; | ||
523 | |||
502 | #define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex) \ | 524 | #define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex) \ |
503 | do { \ | 525 | do { \ |
504 | unsigned long _tmp; \ | 526 | unsigned long _tmp; \ |
@@ -939,39 +961,15 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt, | |||
939 | return rc; | 961 | return rc; |
940 | } | 962 | } |
941 | 963 | ||
942 | static int test_cc(unsigned int condition, unsigned int flags) | 964 | static u8 test_cc(unsigned int condition, unsigned long flags) |
943 | { | 965 | { |
944 | int rc = 0; | 966 | u8 rc; |
967 | void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf); | ||
945 | 968 | ||
946 | switch ((condition & 15) >> 1) { | 969 | flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF; |
947 | case 0: /* o */ | 970 | asm("pushq %[flags]; popf; call *%[fastop]" |
948 | rc |= (flags & EFLG_OF); | 971 | : "=a"(rc) : [fastop]"r"(fop), [flags]"r"(flags)); |
949 | break; | 972 | return rc; |
950 | case 1: /* b/c/nae */ | ||
951 | rc |= (flags & EFLG_CF); | ||
952 | break; | ||
953 | case 2: /* z/e */ | ||
954 | rc |= (flags & EFLG_ZF); | ||
955 | break; | ||
956 | case 3: /* be/na */ | ||
957 | rc |= (flags & (EFLG_CF|EFLG_ZF)); | ||
958 | break; | ||
959 | case 4: /* s */ | ||
960 | rc |= (flags & EFLG_SF); | ||
961 | break; | ||
962 | case 5: /* p/pe */ | ||
963 | rc |= (flags & EFLG_PF); | ||
964 | break; | ||
965 | case 7: /* le/ng */ | ||
966 | rc |= (flags & EFLG_ZF); | ||
967 | /* fall through */ | ||
968 | case 6: /* l/nge */ | ||
969 | rc |= (!(flags & EFLG_SF) != !(flags & EFLG_OF)); | ||
970 | break; | ||
971 | } | ||
972 | |||
973 | /* Odd condition identifiers (lsb == 1) have inverted sense. */ | ||
974 | return (!!rc ^ (condition & 1)); | ||
975 | } | 973 | } |
976 | 974 | ||
977 | static void fetch_register_operand(struct operand *op) | 975 | static void fetch_register_operand(struct operand *op) |