Skip to content

Commit

Permalink
First draft of string instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
Theodore Dubois committed May 24, 2018
1 parent c1f6c4a commit f62a273
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 43 deletions.
1 change: 1 addition & 0 deletions emu/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ struct cpu_state {
};
// for asm
#define AF_FLAG (1 << 4)
#define DF_FLAG (1 << 10)
};
// for maximum efficiency these are stored in bytes
byte_t cf;
Expand Down
22 changes: 11 additions & 11 deletions emu/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,17 +459,17 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) {
READADDR; MOV(reg_a, mem_addr,8); break;
case 0xa3: TRACEI("mov oax, mem\t");
READADDR; MOV(reg_a, mem_addr,oz); break;
case 0xa4: TRACEI("movsb"); MOVS(8); break;
case 0xa5: TRACEI("movs"); MOVS(OP_SIZE); break;
case 0xa4: TRACEI("movsb"); STR(movs, 8); break;
case 0xa5: TRACEI("movs"); STR(movs, oz); break;

case 0xa8: TRACEI("test imm8, al");
READIMM8; TEST(imm, reg_a,8); break;
case 0xa9: TRACEI("test imm, oax");
READIMM; TEST(imm, reg_a,oz); break;

case 0xaa: TRACEI("stosb"); STOS(8); break;
case 0xab: TRACEI("stos"); STOS(OP_SIZE); break;
case 0xac: TRACEI("lodsb"); LODS(8); break;
case 0xaa: TRACEI("stosb"); STR(stos, 8); break;
case 0xab: TRACEI("stos"); STR(stos, oz); break;
case 0xac: TRACEI("lodsb"); STR(lods, 8); break;

case 0xb0: TRACEI("mov imm, al\t");
READIMM8; MOV(imm, reg_a,8); break;
Expand Down Expand Up @@ -633,7 +633,7 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) {
default: TRACE("undefined"); UNDEFINED;
}
break;
case 0xae: TRACEI("repnz scasb"); REPNZ(SCAS(8)); break;
case 0xae: TRACEI("repnz scasb"); REPNZ(scas, 8); break;
default: TRACE("undefined"); UNDEFINED;
}
break;
Expand All @@ -654,13 +654,13 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) {

case 0x90: TRACEI("pause"); break;

case 0xa4: TRACEI("rep movsb"); REP(MOVS(8)); break;
case 0xa5: TRACEI("rep movs"); REP(MOVS(OP_SIZE)); break;
case 0xa4: TRACEI("rep movsb"); REP(movs, 8); break;
case 0xa5: TRACEI("rep movs"); REP(movs, oz); break;

case 0xa6: TRACEI("repz cmpsb"); REPZ(CMPS(8)); break;
case 0xa6: TRACEI("repz cmpsb"); REPZ(cmps, 8); break;

case 0xaa: TRACEI("rep stosb"); REP(STOS(8)); break;
case 0xab: TRACEI("rep stos"); REP(STOS(OP_SIZE)); break;
case 0xaa: TRACEI("rep stosb"); REP(stos, 8); break;
case 0xab: TRACEI("rep stos"); REP(stos, oz); break;

// repz ret is equivalent to ret but on some amd chips there's
// a branch prediction penalty if the target of a branch is a
Expand Down
16 changes: 10 additions & 6 deletions emu/gadgets-x86/gadgets.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@
cmpl TLB_ENTRY_page_if_writable(%_tlb,%r14), %r15d
.endif
movl %r15d, -TLB_entries+TLB_dirty_page(%_tlb)
je 1f
je 2f
call handle_\type\()_miss
1:
2:
addq TLB_ENTRY_data_minus_addr(%_tlb,%r14), %_addrq
.endm

Expand Down Expand Up @@ -80,15 +80,19 @@
.popsection
.endm

.macro .gadget_array type
.macro .gadget_list_size type, list:vararg
_gadget_array_start \type
# sync with enum size
gadgets \type\()8, GADGET_LIST
gadgets \type\()16, GADGET_LIST
gadgets \type\()32, GADGET_LIST
gadgets \type\()8, \list
gadgets \type\()16, \list
gadgets \type\()32, \list
.popsection
.endm

.macro .gadget_array type
.gadget_list_size \type, GADGET_LIST
.endm

.macro _invoke reg, post, macro:vararg
\macro reg_\reg, e\reg\post
.endm
Expand Down
50 changes: 50 additions & 0 deletions emu/gadgets-x86/string.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "gadgets.h"

#define REP_LIST once,rep,repnz

.gadget cld
andl $~DF_FLAG, CPU_eflags(%_cpu)
gret

.macro do_strop op, size, rep
# repnz is only a thing for cmps and scas
.ifc \rep,repnz
.ifnc \rep,cmps; .ifnc \rep,scas
.exitm
.endif; .endif
.endif

.gadget \op\size\()_\rep
1:
.ifc \op,stos
movl %edi, %_addr
write_prep
.if \size == 8
movb %al, (%_addrq)
.elseif \size == 16
movw %ax, (%_addrq)
.elseif \size == 32
movl %eax, (%_addrq)
.endif
addl $(\size/8), %edi
.endif
.ifc \rep,rep
decl %ecx
jnz 1b
.endif
gret
.endm

.irp op, stos
.irp size, 8,16,32
.irp rep, REP_LIST
do_strop \op, \size, \rep
.endr
.endr
.gadget_list_size \op, REP_LIST
.endr
# temporary
.gadget_list_size movs, REP_LIST
.gadget_list_size lods, REP_LIST
.gadget_list_size scas, REP_LIST
.gadget_list_size cmps, REP_LIST
21 changes: 12 additions & 9 deletions emu/gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ enum cond {
cond_count,
};

enum repeat {
rep_once, rep_repz, rep_repnz,
rep_count,
rep_rep = rep_repz,
};

typedef void (*gadget_t)();

#define GEN(thing) gen(state, (unsigned long) (thing))
Expand Down Expand Up @@ -151,7 +157,7 @@ static inline void gen_op(struct gen_state *state, gadget_t *gadgets, enum arg a
#define PUSHF() UNDEFINED
#define POPF() UNDEFINED
#define SAHF UNDEFINED
#define CLD UNDEFINED
#define CLD g(cld)
#define STD UNDEFINED

#define MUL18(val,z) UNDEFINED
Expand Down Expand Up @@ -185,14 +191,11 @@ static inline void gen_op(struct gen_state *state, gadget_t *gadgets, enum arg a

#define BSWAP(dst) UNDEFINED

#define SCAS(z) UNDEFINED
#define MOVS(z) UNDEFINED
#define LODS(z) UNDEFINED
#define STOS(z) UNDEFINED
#define CMPS(z) UNDEFINED
#define REP(op) UNDEFINED
#define REPZ(op) UNDEFINED
#define REPNZ(op) UNDEFINED
#define strop(op, rep, z) ga(op, sz(z) * size_count + rep_##rep)
#define STR(op, z) strop(op, once, z)
#define REP(op, z) strop(op, rep, z)
#define REPZ(op, z) strop(op, repz, z)
#define REPNZ(op, z) strop(op, repnz, z)

#define CMPXCHG(src, dst,z) UNDEFINED
#define XADD(src, dst,z) UNDEFINED
Expand Down
28 changes: 13 additions & 15 deletions emu/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,42 +428,40 @@ static bool modrm_compute(struct cpu_state *cpu, struct tlb *tlb, addr_t *addr_o
#define BUMP_SI_DI(size) \
BUMP_SI(size); BUMP_DI(size)

#define MOVS(z) \
#define str_movs(z) \
mem_write(cpu->edi, mem_read(cpu->esi, z), z); \
BUMP_SI_DI(z)

#define STOS(z) \
#define str_stos(z) \
mem_write(cpu->edi, get(reg_a,z),z); \
BUMP_DI(z)

#define LODS(z) \
#define str_lods(z) \
set(reg_a, mem_read(cpu->esi, z),z); \
BUMP_SI(z)

#define SCAS(z) \
#define str_scas(z) \
CMP(reg_a, mem_di,z); \
BUMP_DI(z)

#define CMPS(z) \
#define str_cmps(z) \
CMP(mem_di, mem_si,z); \
BUMP_SI_DI(z)

#define REP(OP) \
#define STR(op, z) str_##op(z)

#define REP(op, z) \
while (cpu->ecx != 0) { \
OP; \
STR(op, z); \
cpu->ecx--; \
}

#define REPNZ(OP) \
#define REPNZ(op, z) \
while (cpu->ecx != 0) { \
OP; \
STR(op, z); \
cpu->ecx--; \
if (ZF) break; \
}

#define REPZ(OP) \
#define REPZ(op, z) \
while (cpu->ecx != 0) { \
OP; \
STR(op, z); \
cpu->ecx--; \
if (!ZF) break; \
}
Expand Down
1 change: 1 addition & 0 deletions emu/offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ void cpu() {
MACRO(SF_RES);
MACRO(AF_OPS);
MACRO(AF_FLAG);
MACRO(DF_FLAG);

OFFSET(JIT_BLOCK, jit_block, code);

Expand Down
5 changes: 3 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,11 @@ if get_option('jit')
'emu/jit.c',
'emu/gen.c',
'emu/gadgets-x86/entry.S',
'emu/gadgets-x86/memory.S',
'emu/gadgets-x86/control.S',
'emu/gadgets-x86/math.S',
'emu/gadgets-x86/bits.S',
'emu/gadgets-x86/control.S',
'emu/gadgets-x86/memory.S',
'emu/gadgets-x86/string.S',
'emu/gadgets-x86/misc.S',
offsets,
]
Expand Down

0 comments on commit f62a273

Please sign in to comment.