@@ -1301,8 +1301,15 @@ static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
1301
1301
rc -> end = n * size ;
1302
1302
}
1303
1303
1304
- memcpy (dest , rc -> data + rc -> pos , size );
1305
- rc -> pos += size ;
1304
+ if (ctxt -> rep_prefix && !(ctxt -> eflags & EFLG_DF )) {
1305
+ ctxt -> dst .data = rc -> data + rc -> pos ;
1306
+ ctxt -> dst .type = OP_MEM_STR ;
1307
+ ctxt -> dst .count = (rc -> end - rc -> pos ) / size ;
1308
+ rc -> pos = rc -> end ;
1309
+ } else {
1310
+ memcpy (dest , rc -> data + rc -> pos , size );
1311
+ rc -> pos += size ;
1312
+ }
1306
1313
return 1 ;
1307
1314
}
1308
1315
@@ -1546,6 +1553,14 @@ static int writeback(struct x86_emulate_ctxt *ctxt)
1546
1553
if (rc != X86EMUL_CONTINUE )
1547
1554
return rc ;
1548
1555
break ;
1556
+ case OP_MEM_STR :
1557
+ rc = segmented_write (ctxt ,
1558
+ ctxt -> dst .addr .mem ,
1559
+ ctxt -> dst .data ,
1560
+ ctxt -> dst .bytes * ctxt -> dst .count );
1561
+ if (rc != X86EMUL_CONTINUE )
1562
+ return rc ;
1563
+ break ;
1549
1564
case OP_XMM :
1550
1565
write_sse_reg (ctxt , & ctxt -> dst .vec_val , ctxt -> dst .addr .xmm );
1551
1566
break ;
@@ -2793,7 +2808,7 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
2793
2808
static void string_addr_inc (struct x86_emulate_ctxt * ctxt , int reg ,
2794
2809
struct operand * op )
2795
2810
{
2796
- int df = (ctxt -> eflags & EFLG_DF ) ? -1 : 1 ;
2811
+ int df = (ctxt -> eflags & EFLG_DF ) ? - op -> count : op -> count ;
2797
2812
2798
2813
register_address_increment (ctxt , reg_rmw (ctxt , reg ), df * op -> bytes );
2799
2814
op -> addr .mem .ea = register_address (ctxt , reg_read (ctxt , reg ));
@@ -3733,7 +3748,7 @@ static const struct opcode opcode_table[256] = {
3733
3748
I (DstReg | SrcMem | ModRM | Src2Imm , em_imul_3op ),
3734
3749
I (SrcImmByte | Mov | Stack , em_push ),
3735
3750
I (DstReg | SrcMem | ModRM | Src2ImmByte , em_imul_3op ),
3736
- I2bvIP (DstDI | SrcDX | Mov | String , em_in , ins , check_perm_in ), /* insb, insw/insd */
3751
+ I2bvIP (DstDI | SrcDX | Mov | String | Unaligned , em_in , ins , check_perm_in ), /* insb, insw/insd */
3737
3752
I2bvIP (SrcSI | DstDX | String , em_out , outs , check_perm_out ), /* outsb, outsw/outsd */
3738
3753
/* 0x70 - 0x7F */
3739
3754
X16 (D (SrcImmByte )),
@@ -3991,6 +4006,7 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
3991
4006
register_address (ctxt , reg_read (ctxt , VCPU_REGS_RDI ));
3992
4007
op -> addr .mem .seg = VCPU_SREG_ES ;
3993
4008
op -> val = 0 ;
4009
+ op -> count = 1 ;
3994
4010
break ;
3995
4011
case OpDX :
3996
4012
op -> type = OP_REG ;
@@ -4034,6 +4050,7 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
4034
4050
register_address (ctxt , reg_read (ctxt , VCPU_REGS_RSI ));
4035
4051
op -> addr .mem .seg = seg_override (ctxt );
4036
4052
op -> val = 0 ;
4053
+ op -> count = 1 ;
4037
4054
break ;
4038
4055
case OpImmFAddr :
4039
4056
op -> type = OP_IMM ;
@@ -4575,8 +4592,14 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
4575
4592
string_addr_inc (ctxt , VCPU_REGS_RDI , & ctxt -> dst );
4576
4593
4577
4594
if (ctxt -> rep_prefix && (ctxt -> d & String )) {
4595
+ unsigned int count ;
4578
4596
struct read_cache * r = & ctxt -> io_read ;
4579
- register_address_increment (ctxt , reg_rmw (ctxt , VCPU_REGS_RCX ), -1 );
4597
+ if ((ctxt -> d & SrcMask ) == SrcSI )
4598
+ count = ctxt -> src .count ;
4599
+ else
4600
+ count = ctxt -> dst .count ;
4601
+ register_address_increment (ctxt , reg_rmw (ctxt , VCPU_REGS_RCX ),
4602
+ - count );
4580
4603
4581
4604
if (!string_insn_completed (ctxt )) {
4582
4605
/*
0 commit comments