diff options
author | Avi Kivity <avi@redhat.com> | 2010-07-29 08:11:51 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:50:22 -0400 |
commit | ef65c88912cafe56de2737c440aefc764fd8f202 (patch) | |
tree | f9e3ec543228d18234bb2304d0ebd17da39a5364 /arch/x86/kvm/emulate.c | |
parent | 9aabc88fc8687ba3a520e2ec459821d05f72474e (diff) |
KVM: x86 emulator: allow storing emulator execution function in decode tables
Instead of looking up the opcode twice (once for decode flags, once for
the big execution switch) look up both flags and function in the decode tables.
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r-- | arch/x86/kvm/emulate.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 3689f34a303a..799e895fb08e 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -106,6 +106,7 @@ | |||
106 | struct opcode { | 106 | struct opcode { |
107 | u32 flags; | 107 | u32 flags; |
108 | union { | 108 | union { |
109 | int (*execute)(struct x86_emulate_ctxt *ctxt); | ||
109 | struct opcode *group; | 110 | struct opcode *group; |
110 | struct group_dual *gdual; | 111 | struct group_dual *gdual; |
111 | } u; | 112 | } u; |
@@ -120,6 +121,7 @@ struct group_dual { | |||
120 | #define N D(0) | 121 | #define N D(0) |
121 | #define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) } | 122 | #define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) } |
122 | #define GD(_f, _g) { .flags = ((_f) | Group | GroupDual), .u.gdual = (_g) } | 123 | #define GD(_f, _g) { .flags = ((_f) | Group | GroupDual), .u.gdual = (_g) } |
124 | #define I(_f, _e) { .flags = (_f), .u.execute = (_e) } | ||
123 | 125 | ||
124 | static struct opcode group1[] = { | 126 | static struct opcode group1[] = { |
125 | X7(D(Lock)), N | 127 | X7(D(Lock)), N |
@@ -349,6 +351,7 @@ static struct opcode twobyte_table[256] = { | |||
349 | #undef N | 351 | #undef N |
350 | #undef G | 352 | #undef G |
351 | #undef GD | 353 | #undef GD |
354 | #undef I | ||
352 | 355 | ||
353 | /* EFLAGS bit definitions. */ | 356 | /* EFLAGS bit definitions. */ |
354 | #define EFLG_ID (1<<21) | 357 | #define EFLG_ID (1<<21) |
@@ -1070,6 +1073,8 @@ done_prefixes: | |||
1070 | c->d |= opcode.flags; | 1073 | c->d |= opcode.flags; |
1071 | } | 1074 | } |
1072 | 1075 | ||
1076 | c->execute = opcode.u.execute; | ||
1077 | |||
1073 | /* Unrecognised? */ | 1078 | /* Unrecognised? */ |
1074 | if (c->d == 0 || (c->d & Undefined)) { | 1079 | if (c->d == 0 || (c->d & Undefined)) { |
1075 | DPRINTF("Cannot emulate %02x\n", c->b); | 1080 | DPRINTF("Cannot emulate %02x\n", c->b); |
@@ -2705,6 +2710,13 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt) | |||
2705 | 2710 | ||
2706 | special_insn: | 2711 | special_insn: |
2707 | 2712 | ||
2713 | if (c->execute) { | ||
2714 | rc = c->execute(ctxt); | ||
2715 | if (rc != X86EMUL_CONTINUE) | ||
2716 | goto done; | ||
2717 | goto writeback; | ||
2718 | } | ||
2719 | |||
2708 | if (c->twobyte) | 2720 | if (c->twobyte) |
2709 | goto twobyte_insn; | 2721 | goto twobyte_insn; |
2710 | 2722 | ||