Emulator group simplification
cover Emulator group simplification
This patchset simplifies the x86 emulator group decoding, cleans up the decoder tables (and adds a missing Lock marker as well).
Avi Kivity (13):
KVM: x86 emulator: add macros for repetitive instructions
KVM: x86 emulator: consolidate inc/dec reg decoding
KVM: x86 emulator: consolidate push/pop reg decoding
KVM: X86 emulator: consolidate Jcc rel8 decoding
KVM: x86 emulator: consolidate MOV reg, imm decoding
KVM: x86 emulator: consolidate CMOVcc decoding
KVM: x86 emulator: consolidate Jcc rel32 decoding
KVM: x86 emulator: Make group storage bits separate from operand bits
KVM: x86 emulator: add Undefined decode flag
KVM: x86 emulator: mix decode bits from opcode and group decode
tables
KVM: x86 emulator: simplify Group 1 decoding
KVM: x86 emulator: Allow LOCK prefix for NEG and NOT
KVM: x86 emulator: unify the two Group 3 variants
arch/x86/kvm/emulate.c | 143 ++++++++++++++++-------------------------------- 1 files changed, 47 insertions(+), 96 deletions(-)
PATCH 1/13 KVM: x86 emulator: add macros for repetitive instructions
Some instructions are repetitive in the opcode space, add macros for consolidating them.
--- arch/x86/kvm/emulate.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
arch/x86/kvm/emulate.c +9 -0
@@ -94,6 +94,15 @@#define Src2One (3<<29)#define Src2Mask (7<<29) +#define X2 (x) (x), (x) +#define X3 (x) X2(x), (x) +#define X4 (x) X2(x), X2(x) +#define X5 (x) X4(x), (x) +#define X6 (x) X4(x), X2(x) +#define X7 (x) X4(x), X3(x) +#define X8 (x) X4(x), X4(x) +#define X16 (x) X8(x), X8(x) +enum { Group1_80, Group1_81, Group1_82, Group1_83, Group1A, Group3_Byte, Group3, Group4, Group5, Group7,
Signature · 1 line
1.7.1
PATCH 2/13 KVM: x86 emulator: consolidate inc/dec reg decoding
In reply to Avi Kivity--- arch/x86/kvm/emulate.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
arch/x86/kvm/emulate.c +2 -4
@@ -147,10 +147,8 @@ static u32 opcode_table[256] = { ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM, ByteOp | DstAcc | SrcImm, DstAcc | SrcImm,0 ,0 , -/* 0x40 - 0x47 */ - DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, -/* 0x48 - 0x4F */ - DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, DstReg, +/* 0x40 - 0x4F */ +X16 (DstReg),/* 0x50 - 0x57 */ SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack,
Signature · 1 line
1.7.1
PATCH 3/13 KVM: x86 emulator: consolidate push/pop reg decoding
In reply to Avi Kivity--- arch/x86/kvm/emulate.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
arch/x86/kvm/emulate.c +2 -4
@@ -150,11 +150,9 @@ static u32 opcode_table[256] = {/* 0x40 - 0x4F */ X16 (DstReg),/* 0x50 - 0x57 */ - SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, - SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, SrcReg | Stack, +X8 (SrcReg | Stack),/* 0x58 - 0x5F */ - DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack, - DstReg | Stack, DstReg | Stack, DstReg | Stack, DstReg | Stack, +X8 (DstReg | Stack),/* 0x60 - 0x67 */ ImplicitOps | Stack | No64, ImplicitOps | Stack | No64, 0, DstReg | SrcMem32 | ModRM | Mov /* movsxd (x86/64) */ ,
Signature · 1 line
1.7.1
PATCH 4/13 KVM: X86 emulator: consolidate Jcc rel8 decoding
In reply to Avi Kivity--- arch/x86/kvm/emulate.c | 8 ++------ 1 files changed, 2 insertions(+), 6 deletions(-)
arch/x86/kvm/emulate.c +2 -6
@@ -161,12 +161,8 @@ static u32 opcode_table[256] = { SrcImm | Mov | Stack,0 , SrcImmByte | Mov | Stack,0 , DstDI | ByteOp | Mov | String, DstDI | Mov | String,/* insb, insw/insd */ SrcSI | ByteOp | ImplicitOps | String, SrcSI | ImplicitOps | String,/* outsb, outsw/outsd */ -/* 0x70 - 0x77 */ - SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, - SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, -/* 0x78 - 0x7F */ - SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, - SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, +/* 0x70 - 0x7F */ +X16 (SrcImmByte),/* 0x80 - 0x87 */ Group | Group1_80, Group | Group1_81, Group | Group1_82, Group | Group1_83,
Signature · 1 line
1.7.1
PATCH 5/13 KVM: x86 emulator: consolidate MOV reg, imm decoding
In reply to Avi Kivity--- arch/x86/kvm/emulate.c | 10 ++-------- 1 files changed, 2 insertions(+), 8 deletions(-)
arch/x86/kvm/emulate.c +2 -8
@@ -188,15 +188,9 @@ static u32 opcode_table[256] = { ByteOp | SrcSI | DstAcc | Mov | String, SrcSI | DstAcc | Mov | String, ByteOp | DstDI | String, DstDI | String,/* 0xB0 - 0xB7 */ - ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov, - ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov, - ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov, - ByteOp | DstReg | SrcImm | Mov, ByteOp | DstReg | SrcImm | Mov, +X8 (ByteOp | DstReg | SrcImm | Mov),/* 0xB8 - 0xBF */ - DstReg | SrcImm | Mov, DstReg | SrcImm | Mov, - DstReg | SrcImm | Mov, DstReg | SrcImm | Mov, - DstReg | SrcImm | Mov, DstReg | SrcImm | Mov, - DstReg | SrcImm | Mov, DstReg | SrcImm | Mov, +X8 (DstReg | SrcImm | Mov),/* 0xC0 - 0xC7 */ ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, 0, ImplicitOps | Stack, 0, 0,
Signature · 1 line
1.7.1
PATCH 6/13 KVM: x86 emulator: consolidate CMOVcc decoding
In reply to Avi Kivity--- arch/x86/kvm/emulate.c | 12 ++---------- 1 files changed, 2 insertions(+), 10 deletions(-)
arch/x86/kvm/emulate.c +2 -10
@@ -238,16 +238,8 @@ static u32 twobyte_table[256] = { ImplicitOps | Priv,0 , ImplicitOps | Priv,0 , ImplicitOps, ImplicitOps | Priv,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , -/* 0x40 - 0x47 */ - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, -/* 0x48 - 0x4F */ - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, - DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, +/* 0x40 - 0x4F */ +X16 (DstReg | SrcMem | ModRM | Mov),/* 0x50 - 0x5F */ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , /* 0x60 - 0x6F */
Signature · 1 line
1.7.1
PATCH 7/13 KVM: x86 emulator: consolidate Jcc rel32 decoding
In reply to Avi Kivity--- arch/x86/kvm/emulate.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
arch/x86/kvm/emulate.c +1 -2
@@ -247,8 +247,7 @@ static u32 twobyte_table[256] = {/* 0x70 - 0x7F */ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,/* 0x80 - 0x8F */ - SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, - SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, SrcImm, +X16 (SrcImm),/* 0x90 - 0x9F */ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , /* 0xA0 - 0xA7 */
Signature · 1 line
1.7.1
PATCH 8/13 KVM: x86 emulator: Make group storage bits separate from operand bits
In reply to Avi KivityCurrently group bits are stored in bits 0:7, where operand bits are stored.
Make group bits be 0:3, and move the existing bits 0:3 to 16:19, so we can mix group and operand bits.
--- arch/x86/kvm/emulate.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-)
arch/x86/kvm/emulate.c +9 -9
@@ -46,15 +46,15 @@*/ /* Operand sizes: 8-bit operands or specified/overridden size. */ -#define ByteOp (1<<0)/* 8-bit operands. */ +#define ByteOp (1<<16)/* 8-bit operands. */ /* Destination operand type. */ -#define ImplicitOps (1<<1)/* Implicit in opcode. No generic decode. */ -#define DstReg (2<<1)/* Register operand. */ -#define DstMem (3<<1)/* Memory operand. */ -#define DstAcc (4<<1)/* Destination Accumulator */ -#define DstDI (5<<1)/* Destination is in ES:(E)DI */ -#define DstMem64 (6<<1)/* 64bit memory operand */ -#define DstMask (7<<1) +#define ImplicitOps (1<<17)/* Implicit in opcode. No generic decode. */ +#define DstReg (2<<17)/* Register operand. */ +#define DstMem (3<<17)/* Memory operand. */ +#define DstAcc (4<<17)/* Destination Accumulator */ +#define DstDI (5<<17)/* Destination is in ES:(E)DI */ +#define DstMem64 (6<<17)/* 64bit memory operand */ +#define DstMask (7<<17)/* Source operand type. */ #define SrcNone (0<<4)/* No source operand. */ #define SrcImplicit (0<<4)/* Source operand is implicit in the opcode. */
@@ -82,7 +82,7 @@#define Stack (1<<13)/* Stack instruction (push/pop) */ #define Group (1<<14)/* Bits 3:5 of modrm byte extend opcode */ #define GroupDual (1<<15)/* Alternate decoding of mod == 3 */ -#define GroupMask 0xff/* Group number stored in bits 0:7 */ +#define GroupMask 0x0f/* Group number stored in bits 0:3 */ /* Misc flags */ #define Lock (1<<26)/* lock prefix is allowed for the instruction */ #define Priv (1<<27)/* instruction generates #GP if current CPL != 0 */
Signature · 1 line
1.7.1
PATCH 9/13 KVM: x86 emulator: add Undefined decode flag
In reply to Avi KivityAdd a decode flag to indicate the instruction is invalid. Will come in useful later, when we mix decode bits from the opcode and group table.
--- arch/x86/kvm/emulate.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
arch/x86/kvm/emulate.c +2 -1
@@ -84,6 +84,7 @@#define GroupDual (1<<15)/* Alternate decoding of mod == 3 */ #define GroupMask 0x0f/* Group number stored in bits 0:3 */ /* Misc flags */ +#define Undefined (1<<25)/* No Such Instruction */ #define Lock (1<<26)/* lock prefix is allowed for the instruction */ #define Priv (1<<27)/* instruction generates #GP if current CPL != 0 */ #define No64 (1<<28)
@@ -1065,7 +1066,7 @@ done_prefixes: }/* Unrecognised? */ -if (c->d ==0 ) { +if (c->d ==0 || (c->d & Undefined)) {DPRINTF ("Cannot emulate %02x\n" , c->b);return -1 ; }
Signature · 1 line
1.7.1
PATCH 10/13 KVM: x86 emulator: mix decode bits from opcode and group decode tables
In reply to Avi KivityAllow bits that are common to all members of a group to be specified in the opcode table instead of the group table. This allows some simplification of the decode tables.
--- arch/x86/kvm/emulate.c | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-)
arch/x86/kvm/emulate.c +6 -4
@@ -955,7 +955,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)struct decode_cache *c = &ctxt->decode;int rc =X86EMUL_CONTINUE ;int mode = ctxt->mode; -int def_op_bytes, def_ad_bytes, group; +int def_op_bytes, def_ad_bytes, group, dual;/* we cannot decode insn before we complete previous rep insn */
@@ -1055,14 +1055,16 @@ done_prefixes:if (c->d & Group) { group = c->d & GroupMask; + dual = c->d & GroupDual; c->modrm =insn_fetch (u8,1 , c->eip); --c->eip; group = (group <<3 ) + ((c->modrm >>3 ) &7 ); -if ((c->d & GroupDual) && (c->modrm >>6 ) ==3 ) - c->d = group2_table[group]; + c->d &= ~(Group | GroupDual | GroupMask); +if (dual && (c->modrm >>6 ) ==3 ) + c->d |= group2_table[group];else - c->d = group_table[group]; + c->d |= group_table[group]; }/* Unrecognised? */
Signature · 1 line
1.7.1
PATCH 11/13 KVM: x86 emulator: simplify Group 1 decoding
In reply to Avi KivityMove operand decoding to the opcode table, keep lock decoding in the group table. This allows us to get consolidate the four variants of Group 1 into one group.
--- arch/x86/kvm/emulate.c | 47 +++++++---------------------------------------- 1 files changed, 7 insertions(+), 40 deletions(-)
arch/x86/kvm/emulate.c +7 -40
@@ -105,8 +105,7 @@#define X16 (x) X8(x), X8(x)enum { - Group1_80, Group1_81, Group1_82, Group1_83, - Group1A, Group3_Byte, Group3, Group4, Group5, Group7, + Group1, Group1A, Group3_Byte, Group3, Group4, Group5, Group7, Group8, Group9, };
@@ -165,8 +164,10 @@ static u32 opcode_table[256] = {/* 0x70 - 0x7F */ X16 (SrcImmByte),/* 0x80 - 0x87 */ - Group | Group1_80, Group | Group1_81, - Group | Group1_82, Group | Group1_83, + ByteOp | DstMem | SrcImm | ModRM | Group | Group1, + DstMem | SrcImm | ModRM | Group | Group1, + ByteOp | DstMem | SrcImm | ModRM | No64 | Group | Group1, + DstMem | SrcImmByte | ModRM | Group | Group1, ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, ByteOp | DstMem | SrcReg | ModRM | Lock, DstMem | SrcReg | ModRM | Lock,/* 0x88 - 0x8F */
@@ -285,42 +286,8 @@ static u32 twobyte_table[256] = { };static u32 group_table[] = { - [Group1_80*8 ] = - ByteOp | DstMem | SrcImm | ModRM | Lock, - ByteOp | DstMem | SrcImm | ModRM | Lock, - ByteOp | DstMem | SrcImm | ModRM | Lock, - ByteOp | DstMem | SrcImm | ModRM | Lock, - ByteOp | DstMem | SrcImm | ModRM | Lock, - ByteOp | DstMem | SrcImm | ModRM | Lock, - ByteOp | DstMem | SrcImm | ModRM | Lock, - ByteOp | DstMem | SrcImm | ModRM, - [Group1_81*8 ] = - DstMem | SrcImm | ModRM | Lock, - DstMem | SrcImm | ModRM | Lock, - DstMem | SrcImm | ModRM | Lock, - DstMem | SrcImm | ModRM | Lock, - DstMem | SrcImm | ModRM | Lock, - DstMem | SrcImm | ModRM | Lock, - DstMem | SrcImm | ModRM | Lock, - DstMem | SrcImm | ModRM, - [Group1_82*8 ] = - ByteOp | DstMem | SrcImm | ModRM | No64 | Lock, - ByteOp | DstMem | SrcImm | ModRM | No64 | Lock, - ByteOp | DstMem | SrcImm | ModRM | No64 | Lock, - ByteOp | DstMem | SrcImm | ModRM | No64 | Lock, - ByteOp | DstMem | SrcImm | ModRM | No64 | Lock, - ByteOp | DstMem | SrcImm | ModRM | No64 | Lock, - ByteOp | DstMem | SrcImm | ModRM | No64 | Lock, - ByteOp | DstMem | SrcImm | ModRM | No64, - [Group1_83*8 ] = - DstMem | SrcImmByte | ModRM | Lock, - DstMem | SrcImmByte | ModRM | Lock, - DstMem | SrcImmByte | ModRM | Lock, - DstMem | SrcImmByte | ModRM | Lock, - DstMem | SrcImmByte | ModRM | Lock, - DstMem | SrcImmByte | ModRM | Lock, - DstMem | SrcImmByte | ModRM | Lock, - DstMem | SrcImmByte | ModRM, + [Group1*8 ] = +X7 (Lock),0 , [Group1A*8 ] = DstMem | SrcNone | ModRM | Mov | Stack,0 ,0 ,0 ,0 ,0 ,0 ,0 , [Group3_Byte*8] =
Signature · 1 line
1.7.1
PATCH 12/13 KVM: x86 emulator: Allow LOCK prefix for NEG and NOT
In reply to Avi KivityOpcodes F6/2, F6/3, F7/2, F7/3.
--- arch/x86/kvm/emulate.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
arch/x86/kvm/emulate.c +2 -2
@@ -292,11 +292,11 @@ static u32 group_table[] = { DstMem | SrcNone | ModRM | Mov | Stack, 0, 0, 0, 0, 0, 0, 0, [Group3_Byte*8 ] = ByteOp | SrcImm | DstMem | ModRM, ByteOp | SrcImm | DstMem | ModRM, - ByteOp | DstMem | SrcNone | ModRM, ByteOp | DstMem | SrcNone | ModRM, + ByteOp | DstMem | SrcNone | ModRM | Lock, ByteOp | DstMem | SrcNone | ModRM | Lock, 0, 0, 0, 0, [Group3*8 ] = DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM, - DstMem | SrcNone | ModRM, DstMem | SrcNone | ModRM, + DstMem | SrcNone | ModRM | Lock, DstMem | SrcNone | ModRM | Lock, 0, 0, 0, 0, [Group4*8 ] = ByteOp | DstMem | SrcNone | ModRM | Lock, ByteOp | DstMem | SrcNone | ModRM | Lock,
Signature · 1 line
1.7.1
PATCH 13/13 KVM: x86 emulator: unify the two Group 3 variants
In reply to Avi KivityUse just one group table for byte (F6) and word (F7) opcodes.
--- arch/x86/kvm/emulate.c | 11 +++-------- 1 files changed, 3 insertions(+), 8 deletions(-)
arch/x86/kvm/emulate.c +3 -8
@@ -105,8 +105,7 @@#define X16 (x) X8(x), X8(x)enum { - Group1, Group1A, Group3_Byte, Group3, Group4, Group5, Group7, - Group8, Group9, + Group1, Group1A, Group3, Group4, Group5, Group7, Group8, Group9, };static u32 opcode_table[256 ] = {
@@ -217,7 +216,7 @@ static u32 opcode_table[256] = { SrcNone | ByteOp | DstAcc, SrcNone | DstAcc,/* 0xF0 - 0xF7 */ 0 ,0 ,0 ,0 , - ImplicitOps | Priv, ImplicitOps, Group | Group3_Byte, Group | Group3, + ImplicitOps | Priv, ImplicitOps, ByteOp | Group | Group3, Group | Group3,/* 0xF8 - 0xFF */ ImplicitOps,0 , ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, Group | Group4, Group | Group5,
@@ -290,14 +289,10 @@ static u32 group_table[] = { X7(Lock), 0, [Group1A*8 ] = DstMem | SrcNone | ModRM | Mov | Stack, 0, 0, 0, 0, 0, 0, 0, - [Group3_Byte*8 ] = - ByteOp | SrcImm | DstMem | ModRM, ByteOp | SrcImm | DstMem | ModRM, - ByteOp | DstMem | SrcNone | ModRM | Lock, ByteOp | DstMem | SrcNone | ModRM | Lock, - 0, 0, 0, 0, [Group3*8 ] = DstMem | SrcImm | ModRM, DstMem | SrcImm | ModRM, DstMem | SrcNone | ModRM | Lock, DstMem | SrcNone | ModRM | Lock, - 0, 0, 0, 0, + X4(Undefined), [Group4*8 ] = ByteOp | DstMem | SrcNone | ModRM | Lock, ByteOp | DstMem | SrcNone | ModRM | Lock, 0, 0, 0, 0, 0, 0,
Signature · 1 line
1.7.1
Marcelo Tosatti
AppliedQuoted 19 lines · Avi Kivity
This patchset simplifies the x86 emulator group decoding, cleans up the decoder tables (and adds a missing Lock marker as well).
Avi Kivity (13):
KVM: x86 emulator: add macros for repetitive instructions
KVM: x86 emulator: consolidate inc/dec reg decoding
KVM: x86 emulator: consolidate push/pop reg decoding
KVM: X86 emulator: consolidate Jcc rel8 decoding
KVM: x86 emulator: consolidate MOV reg, imm decoding
KVM: x86 emulator: consolidate CMOVcc decoding
KVM: x86 emulator: consolidate Jcc rel32 decoding
KVM: x86 emulator: Make group storage bits separate from operand bits
KVM: x86 emulator: add Undefined decode flag
KVM: x86 emulator: mix decode bits from opcode and group decode
tables
KVM: x86 emulator: simplify Group 1 decoding
KVM: x86 emulator: Allow LOCK prefix for NEG and NOT
KVM: x86 emulator: unify the two Group 3 variants
Quoted 2 lines
arch/x86/kvm/emulate.c | 143 ++++++++++++++++-------------------------------- 1 files changed, 47 insertions(+), 96 deletions(-)
Applied, thanks.