x86_emulator: emulate shld and shrd instructions
cover x86_emulator: emulate shld and shrd instructions
This series of patches emulate instructions shld and shrd. As those instructions have three operands we introduce a decode set for the Src2 operand. By doing this, the opcode descriptor needs to be extend to 32 bit.
So this series of patches:
[1/5] extend the opcode descriptor to 32 bits
[2/5] add Src2 decode set
[3/5] add a new "implied 1" Src decode type
[4/5] add the assembler code for three operands (one operand is stored
in EXC)
[5/5] add the emulation of shld and shrd instructions
PATCH 1/5 x86_emulator: Extend the opcode descriptor
Extend the opcode descriptor to 32 bits. This is needed by the introduction of a new Src2 operand type.
--- arch/x86/kvm/x86_emulate.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
arch/x86/kvm/x86_emulate.c +4 -4
@@ -76,7 +76,7 @@ enum { Group1A, Group3_Byte, Group3, Group4, Group5, Group7, }; -static u16 opcode_table[256 ] = { +static u32 opcode_table[256 ] = {/* 0x00 - 0x07 */ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
@@ -195,7 +195,7 @@ static u16 opcode_table[256] = { ImplicitOps, ImplicitOps, Group | Group4, Group | Group5, }; -static u16 twobyte_table[256 ] = { +static u32 twobyte_table[256 ] = {/* 0x00 - 0x0F */ 0 , Group | GroupDual | Group7,0 ,0 ,0 ,0 , ImplicitOps,0 , ImplicitOps, ImplicitOps,0 ,0 ,0 , ImplicitOps | ModRM,0 ,0 ,
@@ -253,7 +253,7 @@ static u16 twobyte_table[256] = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 }; -static u16 group_table[] = { +static u32 group_table[] = { [Group1_80*8 ] = ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
@@ -297,7 +297,7 @@ static u16 group_table[] = { SrcMem16 | ModRM | Mov, SrcMem | ModRM | ByteOp, }; -static u16 group2_table[] = { +static u32 group2_table[] = { [Group7*8 ] = SrcNone | ModRM,0 ,0 ,0 , SrcNone | ModRM | DstMem | Mov,0 ,
Signature · 1 line
1.6.0.4.623.g171d7
PATCH 2/5 x86_emulator: add Src2 decode set
In reply to Guillaume ThouveninInstruction like shld has three operands, so we need to add a Src2 decode set. We start with Src2None, Src2CL, and Src2ImmByte, Src2One to support shld/shrd and we will expand it later.
--- arch/x86/include/asm/kvm_x86_emulate.h | 1 + arch/x86/kvm/x86_emulate.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 0 deletions(-)
arch/x86/include/asm/kvm_x86_emulate.h +1 -0
@@ -123,6 +123,7 @@ struct decode_cache {u8 ad_bytes;u8 rex_prefix;struct operand src; +struct operand src2;struct operand dst;bool has_seg_override;u8 seg_override;
arch/x86/kvm/x86_emulate.c +29 -0
@@ -70,6 +70,12 @@#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 */ +/* Source 2 operand type */ +#define Src2None (0<<29) +#define Src2CL (1<<29) +#define Src2ImmByte (2<<29) +#define Src2One (3<<29) +#define Src2Mask (7<<29)enum { Group1_80, Group1_81, Group1_82, Group1_83,
@@ -1000,6 +1006,29 @@ done_prefixes:break ; } +/* +* Decode and fetch the second source operand: register, memory +* or immediate. +*/ +switch (c->d & Src2Mask) { +case Src2None: +break ; +case Src2CL: + c->src2.bytes =1 ; + c->src2.val = c->regs[VCPU_REGS_RCX ] &0x8 ; +break ; +case Src2ImmByte: + c->src2.type =OP_IMM ; + c->src2.ptr = (unsigned long *)c->eip; + c->src2.bytes =1 ; + c->src2.val =insn_fetch (u8,1 , c->eip); +break ; +case Src2One: + c->src2.bytes =1 ; + c->src2.val =1 ; +break ; + } +/* Decode and fetch the destination operand: register or memory. */ switch (c->d & DstMask) {case ImplicitOps:
Signature · 1 line
1.6.0.4.623.g171d7
PATCH 3/5 x86_emulator: add a new "implied 1" Src decode type
In reply to Guillaume ThouveninAdd SrcOne operand type when we need to decode an implied '1' like with regular shift instruction
--- arch/x86/kvm/x86_emulate.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-)
arch/x86/kvm/x86_emulate.c +5 -0
@@ -58,6 +58,7 @@#define SrcMem32 (4<<4)/* Memory operand (32-bit). */ #define SrcImm (5<<4)/* Immediate operand. */ #define SrcImmByte (6<<4)/* 8-bit sign-extended immediate operand. */ +#define SrcOne (7<<4)/* Implied '1' */ #define SrcMask (7<<4)/* Generic ModRM decode. */ #define ModRM (1<<7)
@@ -1004,6 +1005,10 @@ done_prefixes: c->src.bytes =1 ; c->src.val =insn_fetch (s8,1 , c->eip);break ; +case SrcOne: + c->src.bytes =1 ; + c->src.val =1 ; +break ; }/*
Signature · 1 line
1.6.0.4.623.g171d7
PATCH 4/5 x86_emulator: add the assembler code for three operands
In reply to Guillaume ThouveninAdd the assembler code for instruction with three operands and one operand is stored in ECX register
--- arch/x86/kvm/x86_emulate.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 39 insertions(+), 0 deletions(-)
arch/x86/kvm/x86_emulate.c +39 -0
@@ -431,6 +431,45 @@ static u32 group2_table[] = {__emulate_2op_nobyte (_op, _src, _dst, _eflags, \"w" ,"r" , _LO32,"r" ,"" ,"r" ) +/* Instruction has three operands and one operand is stored in ECX register */ +#define __emulate_2op_cl (_op, _cl, _src, _dst, _eflags, _suffix, _type) \ + do { \ + unsigned long _tmp; \ + _type _clv = (_cl).val; \ + _type _srcv = (_src).val; \ + _type _dstv = (_dst).val; \ + \ + __asm__ __volatile__ ( \ + _PRE_EFLAGS("0", "5", "2") \ + _op _suffix " %4,%1 \n" \ + _POST_EFLAGS("0", "5", "2") \ + : "=m" (_eflags), "+r" (_dstv), "=&r" (_tmp) \ + : "c" (_clv) , "r" (_srcv), "i" (EFLAGS_MASK) \ + ); \ + \ + (_cl).val = (unsigned long) _clv; \ + (_src).val = (unsigned long) _srcv; \ + (_dst).val = (unsigned long) _dstv; \ + } while (0) + +#define emulate_2op_cl (_op, _cl, _src, _dst, _eflags) \ + do { \ + switch ((_dst).bytes) { \ + case 2: \ + __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, \ + "w", unsigned short); \ + break; \ + case 4: \ + __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, \ + "l", unsigned int); \ + break; \ + case 8: \ + ON64(__emulate_2op_cl(_op, _cl, _src, _dst, _eflags, \ + "q", unsigned long)); \ + break; \ + } \ + } while (0) +#define __emulate_1op (_op, _dst, _eflags, _suffix) \ do { \ unsigned long _tmp; \
Signature · 1 line
1.6.0.4.623.g171d7
PATCH 5/5 x86_emulator: add the emulation of shld and shrd instructions
In reply to Guillaume ThouveninAdd emulation of shld and shrd instructions
--- arch/x86/kvm/x86_emulate.c | 17 +++++++++++++++-- 1 files changed, 15 insertions(+), 2 deletions(-)
arch/x86/kvm/x86_emulate.c +15 -2
@@ -237,9 +237,14 @@ static u32 twobyte_table[256] = {/* 0x90 - 0x9F */ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,/* 0xA0 - 0xA7 */ -0 ,0 ,0 , DstMem | SrcReg | ModRM | BitOp,0 ,0 ,0 ,0 , +0 ,0 ,0 , DstMem | SrcReg | ModRM | BitOp, + DstMem | SrcReg | Src2ImmByte | ModRM, + DstMem | SrcReg | Src2CL | ModRM,0 ,0 ,/* 0xA8 - 0xAF */ -0 ,0 ,0 , DstMem | SrcReg | ModRM | BitOp,0 ,0 , ModRM,0 , +0 ,0 ,0 , DstMem | SrcReg | ModRM | BitOp, + DstMem | SrcReg | Src2ImmByte | ModRM, + DstMem | SrcReg | Src2CL | ModRM, + ModRM,0 ,/* 0xB0 - 0xB7 */ ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,0 , DstMem | SrcReg | ModRM | BitOp,
@@ -2037,12 +2042,20 @@ twobyte_insn: c->src.val &= (c->dst.bytes <<3 ) -1 ;emulate_2op_SrcV_nobyte ("bt" , c->src, c->dst, ctxt->eflags);break ; +case 0xa4 :/* shld imm8, r, r/m */ +case 0xa5 :/* shld cl, r, r/m */ +emulate_2op_cl ("shld" , c->src2, c->src, c->dst, ctxt->eflags); +break ;case 0xab : bts:/* bts */ /* only subword offset */ c->src.val &= (c->dst.bytes <<3 ) -1 ;emulate_2op_SrcV_nobyte ("bts" , c->src, c->dst, ctxt->eflags);break ; +case 0xac :/* shrd imm8, r, r/m */ +case 0xad :/* shrd cl, r, r/m */ +emulate_2op_cl ("shrd" , c->src2, c->src, c->dst, ctxt->eflags); +break ;case 0xae :/* clflush */ break ; case 0xb0 ... 0xb1: /* cmpxchg */
Signature · 1 line
1.6.0.4.623.g171d7
Avi Kivity
AppliedQuoted 5 lines · Guillaume Thouvenin
This series of patches emulate instructions shld and shrd. As those instructions have three operands we introduce a decode set for the Src2 operand. By doing this, the opcode descriptor needs to be extend to 32 bit.
Quoted 8 lines
So this series of patches:
[1/5] extend the opcode descriptor to 32 bits
[2/5] add Src2 decode set
[3/5] add a new "implied 1" Src decode type
[4/5] add the assembler code for three operands (one operand is stored
in EXC)
[5/5] add the emulation of shld and shrd instructions
Applied, thanks.
Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain.