From mboxrd@z Thu Jan 1 00:00:00 1970 From: Avi Kivity Subject: [PATCH 3/8] KVM: x86 emulator: covert SETCC to fastop Date: Sat, 12 Jan 2013 16:32:52 +0200 Message-ID: <1358001177-8952-4-git-send-email-avi.kivity@gmail.com> References: <1358001177-8952-1-git-send-email-avi.kivity@gmail.com> Cc: kvm@vger.kernel.org To: Gleb Natapov , Marcelo Tosatti Return-path: Received: from mail-we0-f172.google.com ([74.125.82.172]:49797 "EHLO mail-we0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753670Ab3ALOdI (ORCPT ); Sat, 12 Jan 2013 09:33:08 -0500 Received: by mail-we0-f172.google.com with SMTP id r3so1344905wey.3 for ; Sat, 12 Jan 2013 06:33:07 -0800 (PST) In-Reply-To: <1358001177-8952-1-git-send-email-avi.kivity@gmail.com> Sender: kvm-owner@vger.kernel.org List-ID: This is a bit of a special case since we don't have the usual byte/word/long/quad switch; instead we switch on the condition code embedded in the instruction. Signed-off-by: Avi Kivity --- arch/x86/kvm/emulate.c | 60 ++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index d641178..f6f615e 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) ON64(FOP3E(op, rax, rbx, cl)) \ FOP_END +/* Special case for SETcc - 1 instruction per cc */ +#define FOP_SETCC(op) ".align 4; " #op " %al; ret \n\t" + +FOP_START(setcc) +FOP_SETCC(seto) +FOP_SETCC(setc) +FOP_SETCC(setz) +FOP_SETCC(setbe) +FOP_SETCC(sets) +FOP_SETCC(setp) +FOP_SETCC(setl) +FOP_SETCC(setle) +FOP_SETCC(setno) +FOP_SETCC(setnc) +FOP_SETCC(setnz) +FOP_SETCC(setnbe) +FOP_SETCC(setns) +FOP_SETCC(setnp) +FOP_SETCC(setnl) +FOP_SETCC(setnle) +FOP_END; + #define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex) \ do { \ unsigned long _tmp; \ @@ -939,39 +961,15 @@ static int read_descriptor(struct x86_emulate_ctxt *ctxt, return rc; } -static int test_cc(unsigned int condition, unsigned int flags) +static u8 test_cc(unsigned int condition, unsigned long flags) { - int rc = 0; + u8 rc; + void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf); - switch ((condition & 15) >> 1) { - case 0: /* o */ - rc |= (flags & EFLG_OF); - break; - case 1: /* b/c/nae */ - rc |= (flags & EFLG_CF); - break; - case 2: /* z/e */ - rc |= (flags & EFLG_ZF); - break; - case 3: /* be/na */ - rc |= (flags & (EFLG_CF|EFLG_ZF)); - break; - case 4: /* s */ - rc |= (flags & EFLG_SF); - break; - case 5: /* p/pe */ - rc |= (flags & EFLG_PF); - break; - case 7: /* le/ng */ - rc |= (flags & EFLG_ZF); - /* fall through */ - case 6: /* l/nge */ - rc |= (!(flags & EFLG_SF) != !(flags & EFLG_OF)); - break; - } - - /* Odd condition identifiers (lsb == 1) have inverted sense. */ - return (!!rc ^ (condition & 1)); + flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF; + asm("pushq %[flags]; popf; call *%[fastop]" + : "=a"(rc) : [fastop]"r"(fop), [flags]"r"(flags)); + return rc; } static void fetch_register_operand(struct operand *op) -- 1.8.0.1