diff --git a/emu/cpu.h b/emu/cpu.h index e7e89b8b..9bd1eade 100644 --- a/emu/cpu.h +++ b/emu/cpu.h @@ -76,6 +76,8 @@ struct cpu_state { #define ZF_FLAG (1 << 6) #define DF_FLAG (1 << 10) }; + // please pretend this doesn't exist + dword_t df_offset; // for maximum efficiency these are stored in bytes byte_t cf; byte_t of; diff --git a/emu/gadgets-x86/string.S b/emu/gadgets-x86/string.S index 96f195ab..6b0fcd4d 100644 --- a/emu/gadgets-x86/string.S +++ b/emu/gadgets-x86/string.S @@ -6,6 +6,10 @@ andl $~DF_FLAG, CPU_eflags(%_cpu) gret +.gadget std + orl $DF_FLAG, CPU_eflags(%_cpu) + gret + .macro do_strop op, size, rep, s, ss, a # repnz is only a thing for cmps and scas .ifc \rep,repnz @@ -20,11 +24,15 @@ jz 2f 1: .endif + movl $-(\size/8), CPU_df_offset(%_cpu) + testl $DF_FLAG, CPU_eflags(%_cpu) + jnz 3f + negl CPU_df_offset(%_cpu) + 3: .ifc \op,stos movl %edi, %_addr write_prep mov\ss %\a, (%_addrq) - .else; .ifc \op,movs movl %esi, %_addr read_prep @@ -34,10 +42,10 @@ mov\ss %tmp\s, (%_addrq) .endif; .endif .ifin(\op, lods,movs,cmps,scas) - addl $(\size/8), %esi + addl CPU_df_offset(%_cpu), %esi .endifin .ifin(\op, movs,stos,cmps) - addl $(\size/8), %edi + addl CPU_df_offset(%_cpu), %edi .endifin .ifc \rep,rep decl %ecx diff --git a/emu/gen.c b/emu/gen.c index be22efd9..74bc32d5 100644 --- a/emu/gen.c +++ b/emu/gen.c @@ -249,7 +249,7 @@ static inline bool gen_op(struct gen_state *state, gadget_t *gadgets, enum arg a #define POPF() UNDEFINED #define SAHF UNDEFINED #define CLD g(cld) -#define STD UNDEFINED +#define STD g(std) #define MUL18(val,z) MUL1(val,z) #define MUL1(val,z) load(val, z); gz(mul, z) diff --git a/emu/offsets.c b/emu/offsets.c index 53313319..3a8bd791 100644 --- a/emu/offsets.c +++ b/emu/offsets.c @@ -29,6 +29,7 @@ void cpu() { OFFSET(CPU, cpu_state, op1); OFFSET(CPU, cpu_state, op2); OFFSET(CPU, cpu_state, flags_res); + OFFSET(CPU, cpu_state, df_offset); MACRO(PF_RES); MACRO(ZF_RES); MACRO(SF_RES);