aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2011-04-24 07:09:59 -0400
committerAvi Kivity <avi@redhat.com>2011-05-22 08:39:48 -0400
commit46561646ce409ad96c22645362c113de04f60bfb (patch)
tree413b3cb9ba7ea24dbe14e87f2eafd2c5839f6e07 /arch
parent781e0743af3c5ba356d55bc60df59f2dded1e938 (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.c80
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