diff options
author | Avi Kivity <avi@redhat.com> | 2011-04-24 07:09:59 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-05-22 08:39:48 -0400 |
commit | 46561646ce409ad96c22645362c113de04f60bfb (patch) | |
tree | 413b3cb9ba7ea24dbe14e87f2eafd2c5839f6e07 /arch | |
parent | 781e0743af3c5ba356d55bc60df59f2dded1e938 (diff) |
KVM: x86 emulator: consolidate group handling
Move all groups into a single field and handle them in a single place. This
saves bits when we add more group types (3 bits -> 7 groups types).
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/emulate.c | 80 |
1 files changed, 40 insertions, 40 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index c1d9116cf3ac..7466abae84bf 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -73,11 +73,12 @@ | |||
73 | #define MemAbs (1<<11) /* Memory operand is absolute displacement */ | 73 | #define MemAbs (1<<11) /* Memory operand is absolute displacement */ |
74 | #define String (1<<12) /* String instruction (rep capable) */ | 74 | #define String (1<<12) /* String instruction (rep capable) */ |
75 | #define Stack (1<<13) /* Stack instruction (push/pop) */ | 75 | #define Stack (1<<13) /* Stack instruction (push/pop) */ |
76 | #define GroupMask (7<<14) /* Opcode uses one of the group mechanisms */ | ||
76 | #define Group (1<<14) /* Bits 3:5 of modrm byte extend opcode */ | 77 | #define Group (1<<14) /* Bits 3:5 of modrm byte extend opcode */ |
77 | #define GroupDual (1<<15) /* Alternate decoding of mod == 3 */ | 78 | #define GroupDual (2<<14) /* Alternate decoding of mod == 3 */ |
78 | #define Prefix (1<<16) /* Instruction varies with 66/f2/f3 prefix */ | 79 | #define Prefix (3<<14) /* Instruction varies with 66/f2/f3 prefix */ |
80 | #define RMExt (4<<14) /* Opcode extension in ModRM r/m if mod == 3 */ | ||
79 | #define Sse (1<<17) /* SSE Vector instruction */ | 81 | #define Sse (1<<17) /* SSE Vector instruction */ |
80 | #define RMExt (1<<18) /* Opcode extension in ModRM r/m if mod == 3 */ | ||
81 | /* Misc flags */ | 82 | /* Misc flags */ |
82 | #define Prot (1<<21) /* instruction generates #UD if not in prot-mode */ | 83 | #define Prot (1<<21) /* instruction generates #UD if not in prot-mode */ |
83 | #define VendorSpecific (1<<22) /* Vendor specific instruction */ | 84 | #define VendorSpecific (1<<22) /* Vendor specific instruction */ |
@@ -2969,7 +2970,7 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt) | |||
2969 | #define N D(0) | 2970 | #define N D(0) |
2970 | #define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) } | 2971 | #define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) } |
2971 | #define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) } | 2972 | #define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) } |
2972 | #define GD(_f, _g) { .flags = ((_f) | Group | GroupDual), .u.gdual = (_g) } | 2973 | #define GD(_f, _g) { .flags = ((_f) | GroupDual), .u.gdual = (_g) } |
2973 | #define I(_f, _e) { .flags = (_f), .u.execute = (_e) } | 2974 | #define I(_f, _e) { .flags = (_f), .u.execute = (_e) } |
2974 | #define II(_f, _e, _i) \ | 2975 | #define II(_f, _e, _i) \ |
2975 | { .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i } | 2976 | { .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i } |
@@ -3337,9 +3338,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) | |||
3337 | struct decode_cache *c = &ctxt->decode; | 3338 | struct decode_cache *c = &ctxt->decode; |
3338 | int rc = X86EMUL_CONTINUE; | 3339 | int rc = X86EMUL_CONTINUE; |
3339 | int mode = ctxt->mode; | 3340 | int mode = ctxt->mode; |
3340 | int def_op_bytes, def_ad_bytes, dual, goffset, simd_prefix; | 3341 | int def_op_bytes, def_ad_bytes, goffset, simd_prefix; |
3341 | bool op_prefix = false; | 3342 | bool op_prefix = false; |
3342 | struct opcode opcode, *g_mod012, *g_mod3; | 3343 | struct opcode opcode; |
3343 | struct operand memop = { .type = OP_NONE }; | 3344 | struct operand memop = { .type = OP_NONE }; |
3344 | 3345 | ||
3345 | c->eip = ctxt->eip; | 3346 | c->eip = ctxt->eip; |
@@ -3433,44 +3434,43 @@ done_prefixes: | |||
3433 | } | 3434 | } |
3434 | c->d = opcode.flags; | 3435 | c->d = opcode.flags; |
3435 | 3436 | ||
3436 | if (c->d & Group) { | 3437 | while (c->d & GroupMask) { |
3437 | dual = c->d & GroupDual; | 3438 | switch (c->d & GroupMask) { |
3438 | c->modrm = insn_fetch(u8, 1, c->eip); | 3439 | case Group: |
3439 | --c->eip; | 3440 | c->modrm = insn_fetch(u8, 1, c->eip); |
3440 | 3441 | --c->eip; | |
3441 | if (c->d & GroupDual) { | 3442 | goffset = (c->modrm >> 3) & 7; |
3442 | g_mod012 = opcode.u.gdual->mod012; | 3443 | opcode = opcode.u.group[goffset]; |
3443 | g_mod3 = opcode.u.gdual->mod3; | 3444 | break; |
3444 | } else | 3445 | case GroupDual: |
3445 | g_mod012 = g_mod3 = opcode.u.group; | 3446 | c->modrm = insn_fetch(u8, 1, c->eip); |
3446 | 3447 | --c->eip; | |
3447 | c->d &= ~(Group | GroupDual); | 3448 | goffset = (c->modrm >> 3) & 7; |
3448 | 3449 | if ((c->modrm >> 6) == 3) | |
3449 | goffset = (c->modrm >> 3) & 7; | 3450 | opcode = opcode.u.gdual->mod3[goffset]; |
3450 | 3451 | else | |
3451 | if ((c->modrm >> 6) == 3) | 3452 | opcode = opcode.u.gdual->mod012[goffset]; |
3452 | opcode = g_mod3[goffset]; | 3453 | break; |
3453 | else | 3454 | case RMExt: |
3454 | opcode = g_mod012[goffset]; | ||
3455 | |||
3456 | if (opcode.flags & RMExt) { | ||
3457 | goffset = c->modrm & 7; | 3455 | goffset = c->modrm & 7; |
3458 | opcode = opcode.u.group[goffset]; | 3456 | opcode = opcode.u.group[goffset]; |
3459 | } | 3457 | break; |
3460 | 3458 | case Prefix: | |
3461 | c->d |= opcode.flags; | 3459 | if (c->rep_prefix && op_prefix) |
3462 | } | 3460 | return X86EMUL_UNHANDLEABLE; |
3463 | 3461 | simd_prefix = op_prefix ? 0x66 : c->rep_prefix; | |
3464 | if (c->d & Prefix) { | 3462 | switch (simd_prefix) { |
3465 | if (c->rep_prefix && op_prefix) | 3463 | case 0x00: opcode = opcode.u.gprefix->pfx_no; break; |
3464 | case 0x66: opcode = opcode.u.gprefix->pfx_66; break; | ||
3465 | case 0xf2: opcode = opcode.u.gprefix->pfx_f2; break; | ||
3466 | case 0xf3: opcode = opcode.u.gprefix->pfx_f3; break; | ||
3467 | } | ||
3468 | break; | ||
3469 | default: | ||
3466 | return X86EMUL_UNHANDLEABLE; | 3470 | return X86EMUL_UNHANDLEABLE; |
3467 | simd_prefix = op_prefix ? 0x66 : c->rep_prefix; | ||
3468 | switch (simd_prefix) { | ||
3469 | case 0x00: opcode = opcode.u.gprefix->pfx_no; break; | ||
3470 | case 0x66: opcode = opcode.u.gprefix->pfx_66; break; | ||
3471 | case 0xf2: opcode = opcode.u.gprefix->pfx_f2; break; | ||
3472 | case 0xf3: opcode = opcode.u.gprefix->pfx_f3; break; | ||
3473 | } | 3471 | } |
3472 | |||
3473 | c->d &= ~GroupMask; | ||
3474 | c->d |= opcode.flags; | 3474 | c->d |= opcode.flags; |
3475 | } | 3475 | } |
3476 | 3476 | ||