On Sat, Jan 12, 2013 at 04:32:52PM +0200, Avi Kivity wrote: > 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 <avi.kivity@xxxxxxxxx> This fails autotest. f9-32 bit guest, but it looks like the failure is in BIOS. > --- > 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 -- Gleb. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html