Skip to content

Commit

Permalink
Compile subtraction of immediates
Browse files Browse the repository at this point in the history
  • Loading branch information
tbodt committed May 8, 2018
1 parent 540d363 commit d91e7b7
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 35 deletions.
21 changes: 13 additions & 8 deletions emu/gadgets-x86/gadgets.S
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jit_exit:
ret

.gadget interrupt
op %tmp
movl (%ip), %tmp
jmp jit_exit

.gadget exit
Expand All @@ -58,14 +58,14 @@ jit_exit:

.macro mem_\type place
movl %addr, %r14d
shll $8, %r14d
shrl $8, %r14d
andl $0x3ff0, %r14d
movl %addr, %tmp
andl $0xfffff000, %tmp
movl %addr, %r15d
andl $0xfffff000, %r15d
.ifc \type,read
cmpl TLB_ENTRY_page(%tlb,%r14), %tmp
cmpl TLB_ENTRY_page(%tlb,%r14), %r15d
.else
cmpl TLB_ENTRY_page_if_writable(%tlb,%r14), %tmp
cmpl TLB_ENTRY_page_if_writable(%tlb,%r14), %r15d
.endif
je 1f
call handle_\type\()_miss
Expand Down Expand Up @@ -122,7 +122,7 @@ segfault:
.type \type\()_gadgets,@object
\type\()_gadgets:
# The following .irp should stay in sync with enum arg in emu/gen.c
.irp arg, eax,ecx,edx,ebx,esp,ebp,esi,edi,ax,cx,dx,bx,sp,bp,si,di,mem32
.irp arg, eax,ecx,edx,ebx,esp,ebp,esi,edi,ax,cx,dx,bx,sp,bp,si,di,imm,mem32
.ifndef gadget_\type\()_\arg
.set gadget_\type\()_\arg, 0
.endif
Expand All @@ -131,9 +131,9 @@ segfault:
.endm

.gadget push
sub $4, %xsp
movl %xsp, %addr
mem_write %tmp
sub $4, %xsp
gret
.gadget pop
movl %xsp, %addr
Expand All @@ -150,6 +150,11 @@ segfault:
.endm
.reg_gadgets store

.gadget sub_imm
subl (%ip), %tmp
gret 1

.data
.gadget_array load
.gadget_array store
.gadget_array sub
9 changes: 2 additions & 7 deletions emu/gadgets-x86/gadgets.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,11 @@
.global gadget_\()\name
gadget_\()\name :
.endm
.macro gret
addq $8, %ip
.macro gret pop=0
addq $((\pop+1)*8), %ip
jmp *-8(%ip)
.endm

.macro op reg
mov (%ip), \reg
addq $8, %ip
.endm

# using a gas macro for this works fine on gcc but not on clang
#define each_reg irp reg, eax,ecx,edx,ebx,ebp,esp,esi,edi

Expand Down
39 changes: 23 additions & 16 deletions emu/gen.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <assert.h>
#include "emu/modrm.h"
#include "emu/gen.h"
#include "emu/interrupt.h"
Expand All @@ -6,11 +7,11 @@
enum arg {
arg_eax, arg_ecx, arg_edx, arg_ebx, arg_esp, arg_ebp, arg_esi, arg_edi,
arg_ax, arg_cx, arg_dx, arg_bx, arg_sp, arg_bp, arg_si, arg_di,
arg_mem32,
arg_imm, arg_mem32,
arg_cnt,
// the following should not be synced with the aforementioned .irp (no gadgets implement them)
arg_al, arg_cl, arg_dl, arg_bl, arg_ah, arg_ch, arg_dh, arg_bh,
arg_modrm_val, arg_modrm_reg, arg_mem_addr, arg_imm, arg_addr, arg_gs,
arg_modrm_val, arg_modrm_reg, arg_mem_addr, arg_addr, arg_gs,
// markers
arg_reg32 = arg_eax, arg_reg16 = arg_ax,
};
Expand All @@ -22,33 +23,39 @@ void gadget_exit();
void gadget_push();
extern gadget_t load_gadgets[arg_cnt];
extern gadget_t store_gadgets[arg_cnt];
extern gadget_t sub_gadgets[arg_cnt];

#define GEN(thing) gen(state, (unsigned long) (thing))
#define G(g) GEN(gadget_##g)
#define GG(g, a) do { GEN(gadget_##g); GEN(a); } while(0)
#define UNDEFINED GG(interrupt, INT_UNDEFINED); return
#define g(g) GEN(gadget_##g)
#define gg(g, a) do { GEN(gadget_##g); GEN(a); } while (0)
#define UNDEFINED do { gg(interrupt, INT_UNDEFINED); return; } while (0)

static inline void gen_op(struct gen_state *state, gadget_t *gadgets, enum arg arg, struct modrm *modrm) {
static inline void gen_op(struct gen_state *state, gadget_t *gadgets, enum arg arg, struct modrm *modrm, uint64_t *imm) {
switch (arg) {
case arg_eax ... arg_edi:
GEN(gadgets[arg]); break;
case arg_modrm_reg:
// TODO find some way to assert that this won't overflow?
GEN(gadgets[modrm->reg + arg_reg32]); break;
arg = modrm->reg + arg_reg32; break;
case arg_modrm_val:
switch (modrm->type) {
case modrm_reg:
GEN(gadgets[modrm->base + arg_reg32]); break;
arg = modrm->base + arg_reg32; break;
default: UNDEFINED;
}
break;
default: UNDEFINED;
default: break;
}
if (arg >= arg_cnt || gadgets[arg] == NULL) {
debugger;
UNDEFINED;
}
GEN(gadgets[arg]);
if (arg == arg_imm)
GEN(*imm);
}
#define GEN_OP(type, thing) gen_op(state, type##_gadgets, arg_##thing, &modrm)
#define op(type, thing) gen_op(state, type##_gadgets, arg_##thing, &modrm, &imm)

#define load(thing) GEN_OP(load, thing)
#define store(thing) GEN_OP(store, thing)
#define load(thing) op(load, thing)
#define store(thing) op(store, thing)

#define DECLARE_LOCALS \
dword_t addr_offset = 0;
Expand All @@ -74,15 +81,15 @@ static inline void gen_op(struct gen_state *state, gadget_t *gadgets, enum arg a
#define ADC(src, dst,z) UNDEFINED
#define SBB(src, dst,z) UNDEFINED
#define AND(src, dst,z) UNDEFINED
#define SUB(src, dst,z) UNDEFINED
#define SUB(src, dst,z) load(dst); op(sub, src); store(dst)
#define XOR(src, dst,z) UNDEFINED
#define CMP(src, dst,z) UNDEFINED
#define TEST(src, dst,z) UNDEFINED
#define NOT(val,z) UNDEFINED
#define NEG(val,z) UNDEFINED

#define POP(thing) UNDEFINED
#define PUSH(thing) load(thing); G(push)
#define PUSH(thing) load(thing); g(push)

#define INC(val,z) UNDEFINED
#define DEC(val,z) UNDEFINED
Expand Down
3 changes: 1 addition & 2 deletions emu/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ static bool modrm_compute(struct cpu_state *cpu, struct tlb *tlb, addr_t *addr_o
}(void)0

#define get_imm(size) ((uint(size)) imm)
#define get_imm8(size) ((int8_t) (uint8_t) imm)

#define get_mem_addr(size) mem_read(addr, size)
#define set_mem_addr(to, size) mem_write(addr, to, size)
Expand Down Expand Up @@ -423,7 +422,7 @@ static bool modrm_compute(struct cpu_state *cpu, struct tlb *tlb, addr_t *addr_o
switch (modrm.opcode) { \
case 0: \
case 1: TRACE("test imm"); \
READIMM8; TEST(imm8, val); break; \
READIMM8; TEST(imm, val); break; \
case 2: TRACE("not"); return INT_UNDEFINED; \
case 3: TRACE("neg"); return INT_UNDEFINED; \
case 4: TRACE("mul"); return INT_UNDEFINED; \
Expand Down
4 changes: 2 additions & 2 deletions emu/interp/sse.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
dst >>= count
#define PSRLQ(count, dst) \
xmm_dst = get(dst,128); \
SRL(get(count,z), xmm_dst.qw[0]); \
SRL(get(count,z), xmm_dst.qw[1]); \
SRL(get(count,), xmm_dst.qw[0]); \
SRL(get(count,), xmm_dst.qw[1]); \
set(dst, xmm_dst,128)

#define XORP(src, dst) \
Expand Down

0 comments on commit d91e7b7

Please sign in to comment.