Skip to content

Commit

Permalink
Add decoder support for atomics
Browse files Browse the repository at this point in the history
  • Loading branch information
tbodt committed Oct 29, 2018
1 parent 254f050 commit ed5cf3b
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 6 deletions.
81 changes: 75 additions & 6 deletions emu/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) {
#define READIMMoz READIMM // there's nothing more permanent than a temporary hack
#define READIMM8 READIMM_(imm, 8); imm = (int8_t) (uint8_t) imm
#define READIMM16 READIMM_(imm, 16)
#define READMODRM_MEM READMODRM; if (modrm.type == modrm_reg) UNDEFINED

restart:
TRACEIP();
Expand Down Expand Up @@ -421,10 +422,7 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) {
case 0x8b: TRACEI("mov modrm, reg");
READMODRM; MOV(modrm_val, modrm_reg,oz); break;

case 0x8d: TRACEI("lea\t\t");
READMODRM;
if (modrm.type == modrm_reg)
UNDEFINED;
case 0x8d: TRACEI("lea\t\t"); READMODRM_MEM;
MOV(addr, modrm_reg,oz); break;

// only gs is supported, and it does nothing
Expand Down Expand Up @@ -625,7 +623,78 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) {
case 0xeb: TRACEI("jmp rel8\t");
READIMM8; JMP_REL(imm); break;

case 0xf0: TRACELN("lock (ignored for now)"); goto restart;
// lock
case 0xf0:
READINSN;
switch (insn) {

#define MAKE_OP_ATOMIC(x, OP, op) \
case x+0x0: TRACEI("lock " op " reg8, modrm8"); \
READMODRM_MEM; ATOMIC_##OP(modrm_reg, modrm_val,8); break; \
case x+0x1: TRACEI("lock " op " reg, modrm"); \
READMODRM_MEM; ATOMIC_##OP(modrm_reg, modrm_val,oz); break; \

MAKE_OP_ATOMIC(0x00, ADD, "add");
MAKE_OP_ATOMIC(0x08, OR, "or");
MAKE_OP_ATOMIC(0x10, ADC, "adc");
MAKE_OP_ATOMIC(0x18, SBB, "sbb");
MAKE_OP_ATOMIC(0x20, AND, "and");
MAKE_OP_ATOMIC(0x28, SUB, "sub");
MAKE_OP_ATOMIC(0x30, XOR, "xor");

#undef MAKE_OP_ATOMIC

#define GRP1_ATOMIC(src, dst,z) \
switch (modrm.opcode) { \
case 0: TRACE("lock add"); ATOMIC_ADD(src, dst,z); break; \
case 1: TRACE("lock or"); ATOMIC_OR(src, dst,z); break; \
case 2: TRACE("lock adc"); ATOMIC_ADC(src, dst,z); break; \
case 3: TRACE("lock sbb"); ATOMIC_SBB(src, dst,z); break; \
case 4: TRACE("lock and"); ATOMIC_AND(src, dst,z); break; \
case 5: TRACE("lock sub"); ATOMIC_SUB(src, dst,z); break; \
case 6: TRACE("lock xor"); ATOMIC_XOR(src, dst,z); break; \
default: TRACE("undefined"); UNDEFINED; \
}

case 0x80: TRACEI("lock grp1 imm8, modrm8");
READMODRM_MEM; READIMM8; GRP1_ATOMIC(imm, modrm_val,8); break;
case 0x81: TRACEI("lock grp1 imm, modrm");
READMODRM_MEM; READIMM; GRP1_ATOMIC(imm, modrm_val,oz); break;
case 0x83: TRACEI("lock grp1 imm8, modrm");
READMODRM_MEM; READIMM8; GRP1_ATOMIC(imm, modrm_val,oz); break;

#undef GRP1_ATOMIC

case 0x0f:
READINSN;
switch (insn) {
case 0xb1: TRACEI("lock cmpxchg reg, modrm");
READMODRM_MEM; ATOMIC_CMPXCHG(modrm_reg, modrm_val,oz); break;

case 0xc0: TRACEI("lock xadd reg8, modrm8");
READMODRM_MEM; ATOMIC_XADD(modrm_reg, modrm_val,8); break;
case 0xc1: TRACEI("lock xadd reg, modrm");
READMODRM_MEM; ATOMIC_XADD(modrm_reg, modrm_val,oz); break;
}
break;

#define GRP5_ATOMIC(val,z) \
switch (modrm.opcode) { \
case 0: TRACE("lock inc"); ATOMIC_INC(val,z); break; \
case 1: TRACE("lock dec"); ATOMIC_DEC(val,z); break; \
default: TRACE("undefined"); UNDEFINED; \
}

case 0xfe: TRACEI("lock grp5 modrm8\t");
READMODRM_MEM; GRP5_ATOMIC(modrm_val,8); break;
case 0xff: TRACEI("lock grp5 modrm\t");
READMODRM_MEM; GRP5_ATOMIC(modrm_val,oz); break;

#undef GRP5_ATOMIC

default: TRACE("undefined"); UNDEFINED;
}
break;

case 0xf2:
READINSN;
Expand All @@ -634,7 +703,7 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) {
READINSN;
switch (insn) {
case 0x2c: TRACEI("cvttsd2si modrm64, reg32");
READMODRM; if (modrm.type == modrm_reg) UNDEFINED; // TODO xmm
READMODRM_MEM; // TODO xmm
CVTTSD2SI(mem_addr_real, modrm_reg); break;
default: TRACE("undefined"); UNDEFINED;
}
Expand Down
12 changes: 12 additions & 0 deletions emu/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,18 @@ static bool modrm_compute(struct cpu_state *cpu, struct tlb *tlb, addr_t *addr_o
#define CPUID() \
do_cpuid(&cpu->eax, &cpu->ebx, &cpu->ecx, &cpu->edx)

// atomic
#define ATOMIC_ADD ADD
#define ATOMIC_OR OR
#define ATOMIC_ADC ADC
#define ATOMIC_SBB SBB
#define ATOMIC_AND AND
#define ATOMIC_SUB SUB
#define ATOMIC_XOR XOR
#define ATOMIC_INC INC
#define ATOMIC_DEC DEC
#define ATOMIC_CMPXCHG CMPXCHG
#define ATOMIC_XADD XADD
#include "emu/interp/sse.h"
#include "emu/interp/fpu.h"

Expand Down
13 changes: 13 additions & 0 deletions jit/gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,19 @@ static inline bool gen_op(struct gen_state *state, gadget_t *gadgets, enum arg a
#define RDTSC g(rdtsc)
#define CPUID() g(cpuid)

// atomic
#define ATOMIC_ADD ADD
#define ATOMIC_OR OR
#define ATOMIC_ADC ADC
#define ATOMIC_SBB SBB
#define ATOMIC_AND AND
#define ATOMIC_SUB SUB
#define ATOMIC_XOR XOR
#define ATOMIC_INC INC
#define ATOMIC_DEC DEC
#define ATOMIC_CMPXCHG CMPXCHG
#define ATOMIC_XADD XADD

// sse
#define XORP(src, dst) UNDEFINED
#define PSRLQ(src, dst) UNDEFINED
Expand Down

0 comments on commit ed5cf3b

Please sign in to comment.