@@ -97,6 +97,22 @@ struct rep_stack {
9797} __attribute__((packed ));
9898
9999
100+ #define CMPFLAGS (asmcon ,eflags ,op1 ,op2 ) \
101+ asm volatile("cmp %1, %2; pushf; pop %0\n\t" \
102+ : "=g" (eflags) : #asmcon (op1), #asmcon (op2))
103+
104+ #define SCASLOOP (bitsize ,asmcon ,eflags ,addr ,eax ,df ,ecx ,repcond ) \
105+ do { \
106+ CMPFLAGS(asmcon,eflags,read_##bitsize(addr),(uint##bitsize##_t)eax); \
107+ addr += df; \
108+ } while (--ecx && (eflags & X86_EFLAGS_ZF)==repcond)
109+
110+ #define CMPSLOOP (bitsize ,asmcon ,eflags ,addr ,source ,df ,ecx ,repcond ) \
111+ do { \
112+ CMPFLAGS(asmcon,eflags,read_##bitsize(addr),read_##bitsize(source)); \
113+ addr += df; source += df; \
114+ } while (--ecx && (eflags & X86_EFLAGS_ZF)==repcond)
115+
100116void rep_movs_stos (struct rep_stack * stack )
101117{
102118 unsigned char * paddr = stack -> edi ;
@@ -191,26 +207,30 @@ void rep_movs_stos(struct rep_stack *stack)
191207 if (EFLAGS & EFLAGS_DF ) addr -= len ;
192208 else addr += len ;
193209 }
194- else if ((op & 0xf6 ) == 0xa6 ) { /* cmps/scas */
195- int repmod = (size == 1 ? MBYTE : size == 2 ? DATA16 : 0 );
196- AR1 .d = EMUADDR_REL (stack -> edi );
197- TR1 .d = stack -> ecx ;
198- repmod |= MOVSDST |MREPCOND |(eip [-1 ]== REPNE ? MREPNE :MREP );
210+ else if ((op & 0xf6 ) == 0xa6 && ecx > 0 ) { /* cmps/scas */
211+ int df = size * (CPUWORD (Ofs_FLAGS ) & EFLAGS_DF ? -1 :1 );
212+ unsigned long repcond = (eip [-1 ]== REPNE ? 0 : X86_EFLAGS_ZF );
213+ unsigned long eflags ;
199214 if ((op & 0xfe ) == 0xa6 ) { /* cmps */
200- repmod |= MOVSSRC ;
201- AR2 .d = EMUADDR_REL (stack -> esi );
202- IGen IG = (IGen ){.op = O_MOVS_CmpD , .mode = repmod };
203- Gen_sim (& IG );
204- stack -> esi = EMU_BASE32 (AR2 .d );
215+ dosaddr_t source = EMUADDR_REL (stack -> esi );
216+ if (size == 1 )
217+ CMPSLOOP (8 ,q ,eflags ,addr ,source ,df ,ecx ,repcond );
218+ else if (size == 2 )
219+ CMPSLOOP (16 ,r ,eflags ,addr ,source ,df ,ecx ,repcond );
220+ else
221+ CMPSLOOP (32 ,r ,eflags ,addr ,source ,df ,ecx ,repcond );
222+ stack -> esi = EMU_BASE32 (source );
205223 }
206224 else { /* scas */
207- DR1 .d = stack -> eax ;
208- IGen IG = (IGen ){.op = O_MOVS_ScaD , .mode = repmod };
209- Gen_sim (& IG );
225+ unsigned int eax = stack -> eax ;
226+ if (size == 1 )
227+ SCASLOOP (8 ,q ,eflags ,addr ,eax ,df ,ecx ,repcond );
228+ else if (size == 2 )
229+ SCASLOOP (16 ,r ,eflags ,addr ,eax ,df ,ecx ,repcond );
230+ else
231+ SCASLOOP (32 ,r ,eflags ,addr ,eax ,df ,ecx ,repcond );
210232 }
211- addr = AR1 .d ;
212- ecx = TR1 .d ;
213- stack -> eflags = (stack -> eflags & ~EFLAGS_CC ) | FlagSync_All ();
233+ stack -> eflags = (stack -> eflags & ~EFLAGS_CC ) | (eflags & EFLAGS_CC );
214234 }
215235 stack -> edi = EMU_BASE32 (addr );
216236 stack -> ecx = ecx ;
0 commit comments