Added code generation for immediate->register and register versions of MOV, XCHG, ADD, SUB, AND, OR, XOR, TEST, CMP, INC and DEC.
This commit is contained in:
parent
00f6271ec8
commit
630592125c
11 changed files with 1568 additions and 30 deletions
|
|
@ -4,7 +4,7 @@ CC = gcc.exe
|
|||
WINDRES = windres.exe
|
||||
CFLAGS = -O3 -march=i686 -fomit-frame-pointer
|
||||
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \
|
||||
codegen.o codegen_timing_486.o codegen_timing_pentium.o codegen_x86.o config.o cpu.o dac.o \
|
||||
codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_pentium.o codegen_x86.o config.o cpu.o dac.o \
|
||||
device.o dma.o fdc.o gameport.o headland.o i430lx.o i430fx.o i430vx.o ide.o intel.o \
|
||||
intel_flash.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o keyboard_olim24.o \
|
||||
keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o mouse.o mouse_ps2.o mouse_serial.o \
|
||||
|
|
|
|||
|
|
@ -72,4 +72,38 @@ extern codegen_timing_t codegen_timing_486;
|
|||
|
||||
void codegen_timing_set(codegen_timing_t *timing);
|
||||
|
||||
extern int block_current;
|
||||
extern int block_pos;
|
||||
|
||||
#define CPU_BLOCK_END() cpu_block_end = 1
|
||||
|
||||
static inline void addbyte(uint8_t val)
|
||||
{
|
||||
codeblock[block_current].data[block_pos++] = val;
|
||||
if (block_pos >= 8000)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addword(uint16_t val)
|
||||
{
|
||||
*(uint16_t *)&codeblock[block_current].data[block_pos] = val;
|
||||
block_pos += 2;
|
||||
if (block_pos >= 8000)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addlong(uint32_t val)
|
||||
{
|
||||
*(uint32_t *)&codeblock[block_current].data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= 8000)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
64
src/codegen_ops.c
Normal file
64
src/codegen_ops.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#ifdef DYNAREC
|
||||
|
||||
#include "ibm.h"
|
||||
#include "x86.h"
|
||||
#include "x86_ops.h"
|
||||
#include "x86_flags.h"
|
||||
#include "386_common.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_ops.h"
|
||||
#include "codegen_ops_x86.h"
|
||||
|
||||
#include "codegen_ops_arith.h"
|
||||
#include "codegen_ops_logic.h"
|
||||
#include "codegen_ops_mov.h"
|
||||
#include "codegen_ops_xchg.h"
|
||||
|
||||
RecompOpFn recomp_opcodes[512] =
|
||||
{
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, NULL, NULL, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, NULL, NULL,
|
||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL,
|
||||
/*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL,
|
||||
|
||||
/*40*/ ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw,
|
||||
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_b, ropXCHG_w, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, NULL, NULL, NULL,
|
||||
/*90*/ NULL, ropXCHG_AX_CX, ropXCHG_AX_DX, ropXCHG_AX_BX, ropXCHG_AX_SP, ropXCHG_AX_BP, ropXCHG_AX_SI, ropXCHG_AX_DI, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm,
|
||||
|
||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/*32-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, NULL, NULL, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, NULL, NULL,
|
||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL,
|
||||
/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL,
|
||||
|
||||
/*40*/ ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl,
|
||||
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_b, ropXCHG_l, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, NULL, NULL, NULL,
|
||||
/*90*/ NULL, ropXCHG_EAX_ECX,ropXCHG_EAX_EDX,ropXCHG_EAX_EBX,ropXCHG_EAX_ESP,ropXCHG_EAX_EBP,ropXCHG_EAX_ESI,ropXCHG_EAX_EDI,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm,
|
||||
|
||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
|
||||
#endif
|
||||
28
src/codegen_ops.h
Normal file
28
src/codegen_ops.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
typedef uint32_t (*RecompOpFn)(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block);
|
||||
|
||||
extern RecompOpFn recomp_opcodes[512];
|
||||
|
||||
#define REG_EAX 0
|
||||
#define REG_ECX 1
|
||||
#define REG_EDX 2
|
||||
#define REG_EBX 3
|
||||
#define REG_ESP 4
|
||||
#define REG_EBP 5
|
||||
#define REG_ESI 6
|
||||
#define REG_EDI 7
|
||||
#define REG_AX 0
|
||||
#define REG_CX 1
|
||||
#define REG_DX 2
|
||||
#define REG_BX 3
|
||||
#define REG_SP 4
|
||||
#define REG_BP 5
|
||||
#define REG_SI 6
|
||||
#define REG_DI 7
|
||||
#define REG_AL 0
|
||||
#define REG_AH 4
|
||||
#define REG_CL 1
|
||||
#define REG_CH 5
|
||||
#define REG_DL 2
|
||||
#define REG_DH 6
|
||||
#define REG_BL 3
|
||||
#define REG_BH 7
|
||||
621
src/codegen_ops_arith.h
Normal file
621
src/codegen_ops_arith.h
Normal file
|
|
@ -0,0 +1,621 @@
|
|||
static uint32_t ropINC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(opcode & 7);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, 1);
|
||||
AND_HOST_REG_IMM(host_reg, 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD16);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropINC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(opcode & 7);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD32);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropDEC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(opcode & 7);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, 1);
|
||||
AND_HOST_REG_IMM(host_reg, 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(opcode & 7);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
#define ROP_ARITH(name, op, writeback) \
|
||||
static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_B(fetchdat & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 8); \
|
||||
src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \
|
||||
op ## _HOST_REG_B(dst_reg, src_reg); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \
|
||||
FLAG_C_COPY(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_B_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_W(fetchdat & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 16); \
|
||||
src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \
|
||||
op ## _HOST_REG_W(dst_reg, src_reg); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \
|
||||
FLAG_C_COPY(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_W_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_L(fetchdat & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 32); \
|
||||
src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \
|
||||
op ## _HOST_REG_L(dst_reg, src_reg); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \
|
||||
FLAG_C_COPY(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_L_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 8); \
|
||||
src_reg = LOAD_REG_B(fetchdat & 7); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \
|
||||
op ## _HOST_REG_B(dst_reg, src_reg); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \
|
||||
FLAG_C_COPY(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_B_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 16); \
|
||||
src_reg = LOAD_REG_W(fetchdat & 7); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \
|
||||
op ## _HOST_REG_W(dst_reg, src_reg); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \
|
||||
FLAG_C_COPY(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_W_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 32); \
|
||||
src_reg = LOAD_REG_L(fetchdat & 7); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \
|
||||
op ## _HOST_REG_L(dst_reg, src_reg); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \
|
||||
FLAG_C_COPY(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_L_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
}
|
||||
|
||||
ROP_ARITH(ADD, ADD, 1)
|
||||
ROP_ARITH(SUB, SUB, 1)
|
||||
ROP_ARITH(CMP, SUB, 0)
|
||||
|
||||
static uint32_t ropADD_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(REG_AL);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM_B(host_reg, fetchdat & 0xff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD8);
|
||||
FLAG_C_COPY();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_B_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropADD_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(REG_AX);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD16);
|
||||
FLAG_C_COPY();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropADD_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(REG_EAX);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
ADD_HOST_REG_IMM(host_reg, fetchdat);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD32);
|
||||
FLAG_C_COPY();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 4;
|
||||
}
|
||||
|
||||
static uint32_t ropCMP_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(REG_AL);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_B(host_reg, fetchdat & 0xff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB8);
|
||||
FLAG_C_COPY();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropCMP_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(REG_AX);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16);
|
||||
FLAG_C_COPY();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropCMP_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(REG_EAX);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
SUB_HOST_REG_IMM(host_reg, fetchdat);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32);
|
||||
FLAG_C_COPY();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + 4;
|
||||
}
|
||||
|
||||
static uint32_t ropSUB_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(REG_AL);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_B(host_reg, fetchdat & 0xff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB8);
|
||||
FLAG_C_COPY();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_B_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropSUB_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(REG_AX);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16);
|
||||
FLAG_C_COPY();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropSUB_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(REG_EAX);
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
SUB_HOST_REG_IMM(host_reg, fetchdat);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32);
|
||||
FLAG_C_COPY();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 4;
|
||||
}
|
||||
|
||||
static uint32_t rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
uint32_t imm;
|
||||
|
||||
if ((fetchdat & 0x30) == 0x10 || (fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
imm = (fetchdat >> 8) & 0xff;
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*ADD*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM_B(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD8);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
case 0x08: /*OR*/
|
||||
OR_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x20: /*AND*/
|
||||
AND_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x28: /*SUB*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_B(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD8);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
case 0x30: /*XOR*/
|
||||
XOR_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x38: /*CMP*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_B(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB8);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
}
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
if ((fetchdat & 0x38) != 0x38)
|
||||
STORE_REG_B_RELEASE(host_reg);
|
||||
else
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
static uint32_t rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
uint32_t imm;
|
||||
|
||||
if ((fetchdat & 0x30) == 0x10 || (fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
imm = (fetchdat >> 8) & 0xffff;
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*ADD*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM_W(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD16);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
case 0x08: /*OR*/
|
||||
OR_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x20: /*AND*/
|
||||
AND_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x28: /*SUB*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_W(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
case 0x30: /*XOR*/
|
||||
XOR_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x38: /*CMP*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_W(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
}
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
if ((fetchdat & 0x38) != 0x38)
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
else
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + 3;
|
||||
}
|
||||
static uint32_t rop81_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
uint32_t imm;
|
||||
|
||||
if ((fetchdat & 0x30) == 0x10 || (fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
imm = fastreadl(cs + op_pc + 1);
|
||||
|
||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*ADD*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD32);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
case 0x08: /*OR*/
|
||||
OR_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x20: /*AND*/
|
||||
AND_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x28: /*SUB*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
case 0x30: /*XOR*/
|
||||
XOR_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x38: /*CMP*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
}
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
if ((fetchdat & 0x38) != 0x38)
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
else
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + 5;
|
||||
}
|
||||
|
||||
static uint32_t rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
uint32_t imm;
|
||||
|
||||
if ((fetchdat & 0x30) == 0x10 || (fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
imm = (fetchdat >> 8) & 0xff;
|
||||
if (imm & 0x80)
|
||||
imm |= 0xff80;
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*ADD*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM_W(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD16);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
case 0x08: /*OR*/
|
||||
OR_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x20: /*AND*/
|
||||
AND_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x28: /*SUB*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_W(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
case 0x30: /*XOR*/
|
||||
XOR_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x38: /*CMP*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_W(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
}
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
if ((fetchdat & 0x38) != 0x38)
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
else
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t rop83_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
uint32_t imm;
|
||||
|
||||
if ((fetchdat & 0x30) == 0x10 || (fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
imm = (fetchdat >> 8) & 0xff;
|
||||
if (imm & 0x80)
|
||||
imm |= 0xffffff80;
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*ADD*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD32);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
case 0x08: /*OR*/
|
||||
OR_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x20: /*AND*/
|
||||
AND_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x28: /*SUB*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
case 0x30: /*XOR*/
|
||||
XOR_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32);
|
||||
FLAG_C_CLEAR();
|
||||
break;
|
||||
case 0x38: /*CMP*/
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM(host_reg, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32);
|
||||
FLAG_C_COPY();
|
||||
break;
|
||||
}
|
||||
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
if ((fetchdat & 0x38) != 0x38)
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
else
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
273
src/codegen_ops_logic.h
Normal file
273
src/codegen_ops_logic.h
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
#define ROP_LOGIC(name, op, writeback) \
|
||||
static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_B(fetchdat & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); \
|
||||
src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \
|
||||
op ## _HOST_REG_B(dst_reg, src_reg); \
|
||||
FLAG_C_CLEAR(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_B_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_W(fetchdat & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); \
|
||||
src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \
|
||||
op ## _HOST_REG_W(dst_reg, src_reg); \
|
||||
FLAG_C_CLEAR(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_W_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_L(fetchdat & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32); \
|
||||
src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \
|
||||
op ## _HOST_REG_L(dst_reg, src_reg); \
|
||||
FLAG_C_CLEAR(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_L_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); \
|
||||
src_reg = LOAD_REG_B(fetchdat & 7); \
|
||||
op ## _HOST_REG_B(dst_reg, src_reg); \
|
||||
FLAG_C_CLEAR(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_B_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); \
|
||||
src_reg = LOAD_REG_W(fetchdat & 7); \
|
||||
op ## _HOST_REG_W(dst_reg, src_reg); \
|
||||
FLAG_C_CLEAR(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_W_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
\
|
||||
dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32); \
|
||||
src_reg = LOAD_REG_L(fetchdat & 7); \
|
||||
op ## _HOST_REG_L(dst_reg, src_reg); \
|
||||
FLAG_C_CLEAR(); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \
|
||||
if (writeback) STORE_REG_L_RELEASE(dst_reg); \
|
||||
else RELEASE_REG(dst_reg); \
|
||||
RELEASE_REG(src_reg); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
}
|
||||
|
||||
ROP_LOGIC(AND, AND, 1)
|
||||
ROP_LOGIC(OR, OR, 1)
|
||||
ROP_LOGIC(TEST, AND, 0)
|
||||
ROP_LOGIC(XOR, XOR, 1)
|
||||
|
||||
static uint32_t ropAND_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(REG_AL);
|
||||
|
||||
AND_HOST_REG_IMM(host_reg, fetchdat & 0xff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_B_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropAND_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(REG_AX);
|
||||
|
||||
AND_HOST_REG_IMM(host_reg, fetchdat & 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropAND_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(REG_EAX);
|
||||
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
AND_HOST_REG_IMM(host_reg, fetchdat);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 4;
|
||||
}
|
||||
|
||||
static uint32_t ropOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(REG_AL);
|
||||
|
||||
OR_HOST_REG_IMM(host_reg, fetchdat & 0xff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_B_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(REG_AX);
|
||||
|
||||
OR_HOST_REG_IMM(host_reg, fetchdat & 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(REG_EAX);
|
||||
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
OR_HOST_REG_IMM(host_reg, fetchdat);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 4;
|
||||
}
|
||||
|
||||
static uint32_t ropTEST_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(REG_AL);
|
||||
|
||||
AND_HOST_REG_IMM(host_reg, fetchdat & 0xff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropTEST_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(REG_AX);
|
||||
|
||||
AND_HOST_REG_IMM(host_reg, fetchdat & 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropTEST_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(REG_EAX);
|
||||
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
AND_HOST_REG_IMM(host_reg, fetchdat);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + 4;
|
||||
}
|
||||
|
||||
static uint32_t ropXOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(REG_AL);
|
||||
|
||||
XOR_HOST_REG_IMM(host_reg, fetchdat & 0xff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_B_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropXOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(REG_AX);
|
||||
|
||||
XOR_HOST_REG_IMM(host_reg, fetchdat & 0xffff);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(REG_EAX);
|
||||
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
XOR_HOST_REG_IMM(host_reg, fetchdat);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32);
|
||||
FLAG_C_CLEAR();
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg);
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
|
||||
return op_pc + 4;
|
||||
}
|
||||
|
||||
130
src/codegen_ops_mov.h
Normal file
130
src/codegen_ops_mov.h
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
static uint32_t ropMOV_rb_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
STORE_IMM_REG_B(opcode & 7, fetchdat & 0xff);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOV_rw_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
STORE_IMM_REG_W(opcode & 7, fetchdat & 0xffff);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
fetchdat = fastreadl(cs + op_pc);
|
||||
|
||||
STORE_IMM_REG_L(opcode & 7, fetchdat);
|
||||
|
||||
return op_pc + 4;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t ropMOV_b_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_B((fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_B_RELEASE(host_reg, fetchdat & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOV_w_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_W((fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOV_l_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_L((fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropMOV_r_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOV_r_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOV_r_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropMOV_b_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropMOV_w_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff);
|
||||
|
||||
return op_pc + 3;
|
||||
}
|
||||
static uint32_t ropMOV_l_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t imm = fastreadl(cs + op_pc + 1);
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
STORE_IMM_REG_L(fetchdat & 7, imm);
|
||||
|
||||
return op_pc + 5;
|
||||
}
|
||||
305
src/codegen_ops_x86.h
Normal file
305
src/codegen_ops_x86.h
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
static inline int find_host_reg()
|
||||
{
|
||||
int c;
|
||||
for (c = 0; c < NR_HOST_REGS; c++)
|
||||
{
|
||||
if (host_reg_mapping[c] == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == NR_HOST_REGS)
|
||||
fatal("Out of host regs!\n");
|
||||
return c;
|
||||
}
|
||||
|
||||
static void STORE_IMM_ADDR_B(uintptr_t addr, uint8_t val)
|
||||
{
|
||||
addbyte(0xC6); /*MOVB [addr],val*/
|
||||
addbyte(0x05);
|
||||
addlong(addr);
|
||||
addbyte(val);
|
||||
}
|
||||
static void STORE_IMM_ADDR_W(uintptr_t addr, uint16_t val)
|
||||
{
|
||||
addbyte(0x66); /*MOVW [addr],val*/
|
||||
addbyte(0xC7);
|
||||
addbyte(0x05);
|
||||
addlong(addr);
|
||||
addword(val);
|
||||
}
|
||||
static void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val)
|
||||
{
|
||||
addbyte(0xC7); /*MOVL [addr],val*/
|
||||
addbyte(0x05);
|
||||
addlong(addr);
|
||||
addlong(val);
|
||||
}
|
||||
|
||||
static void STORE_IMM_REG_B(int reg, uint8_t val)
|
||||
{
|
||||
addbyte(0xC6); /*MOVB [addr],val*/
|
||||
addbyte(0x05);
|
||||
if (reg & 4)
|
||||
addlong((uint32_t)®s[reg & 3].b.h);
|
||||
else
|
||||
addlong((uint32_t)®s[reg & 3].b.l);
|
||||
addbyte(val);
|
||||
}
|
||||
static void STORE_IMM_REG_W(int reg, uint16_t val)
|
||||
{
|
||||
addbyte(0x66); /*MOVW [addr],val*/
|
||||
addbyte(0xC7);
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)®s[reg & 7].w);
|
||||
addword(val);
|
||||
}
|
||||
static void STORE_IMM_REG_L(int reg, uint32_t val)
|
||||
{
|
||||
addbyte(0xC7); /*MOVL [addr],val*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)®s[reg & 7].l);
|
||||
addlong(val);
|
||||
}
|
||||
|
||||
static int LOAD_REG_B(int reg)
|
||||
{
|
||||
int host_reg = find_host_reg();
|
||||
host_reg_mapping[host_reg] = reg;
|
||||
|
||||
addbyte(0x0f); /*MOVZX B[reg],host_reg*/
|
||||
addbyte(0xb6);
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
if (reg & 4)
|
||||
addlong((uint32_t)®s[reg & 3].b.h);
|
||||
else
|
||||
addlong((uint32_t)®s[reg & 3].b.l);
|
||||
|
||||
return host_reg;
|
||||
}
|
||||
static int LOAD_REG_W(int reg)
|
||||
{
|
||||
int host_reg = find_host_reg();
|
||||
host_reg_mapping[host_reg] = reg;
|
||||
|
||||
addbyte(0x0f); /*MOVZX W[reg],host_reg*/
|
||||
addbyte(0xb7);
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
addlong((uint32_t)®s[host_reg_mapping[host_reg]].w);
|
||||
|
||||
return host_reg;
|
||||
}
|
||||
static int LOAD_REG_L(int reg)
|
||||
{
|
||||
int host_reg = find_host_reg();
|
||||
host_reg_mapping[host_reg] = reg;
|
||||
|
||||
addbyte(0x8b); /*MOVL host_reg,[reg]*/
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
addlong((uint32_t)®s[host_reg_mapping[host_reg]].l);
|
||||
|
||||
return host_reg;
|
||||
}
|
||||
|
||||
static void STORE_REG_B_RELEASE(int host_reg)
|
||||
{
|
||||
addbyte(0x88); /*MOVB [reg],host_reg*/
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
if (host_reg_mapping[host_reg] & 4)
|
||||
addlong((uint32_t)®s[host_reg_mapping[host_reg] & 3].b.h);
|
||||
else
|
||||
addlong((uint32_t)®s[host_reg_mapping[host_reg] & 3].b.l);
|
||||
host_reg_mapping[host_reg] = -1;
|
||||
}
|
||||
static void STORE_REG_W_RELEASE(int host_reg)
|
||||
{
|
||||
addbyte(0x66); /*MOVW [reg],host_reg*/
|
||||
addbyte(0x89);
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
addlong((uint32_t)®s[host_reg_mapping[host_reg]].w);
|
||||
host_reg_mapping[host_reg] = -1;
|
||||
}
|
||||
static void STORE_REG_L_RELEASE(int host_reg)
|
||||
{
|
||||
addbyte(0x89); /*MOVL [reg],host_reg*/
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
addlong((uint32_t)®s[host_reg_mapping[host_reg]].l);
|
||||
host_reg_mapping[host_reg] = -1;
|
||||
}
|
||||
|
||||
static void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg)
|
||||
{
|
||||
addbyte(0x88); /*MOVB [guest_reg],host_reg*/
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
if (guest_reg & 4)
|
||||
addlong((uint32_t)®s[guest_reg & 3].b.h);
|
||||
else
|
||||
addlong((uint32_t)®s[guest_reg & 3].b.l);
|
||||
host_reg_mapping[host_reg] = -1;
|
||||
}
|
||||
static void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg)
|
||||
{
|
||||
addbyte(0x66); /*MOVB [guest_reg],host_reg*/
|
||||
addbyte(0x89);
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
addlong((uint32_t)®s[guest_reg & 7].w);
|
||||
host_reg_mapping[host_reg] = -1;
|
||||
}
|
||||
static void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg)
|
||||
{
|
||||
addbyte(0x89); /*MOVB [guest_reg],host_reg*/
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
addlong((uint32_t)®s[guest_reg & 7].l);
|
||||
host_reg_mapping[host_reg] = -1;
|
||||
}
|
||||
|
||||
static void RELEASE_REG(int host_reg)
|
||||
{
|
||||
host_reg_mapping[host_reg] = -1;
|
||||
}
|
||||
|
||||
static void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg)
|
||||
{
|
||||
addbyte(0x89); /*MOVL [reg],host_reg*/
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
addlong(addr);
|
||||
}
|
||||
|
||||
static void ADD_HOST_REG_B(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x00); /*ADDB dst_reg, src_reg*/
|
||||
addbyte(0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
static void ADD_HOST_REG_W(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*ADDW dst_reg, src_reg*/
|
||||
addbyte(0x01);
|
||||
addbyte(0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
static void ADD_HOST_REG_L(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x01); /*ADDL dst_reg, src_reg*/
|
||||
addbyte(0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
static void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm)
|
||||
{
|
||||
addbyte(0x80); /*ADDB host_reg, imm*/
|
||||
addbyte(0xC0 | host_reg);
|
||||
addbyte(imm);
|
||||
}
|
||||
static void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm)
|
||||
{
|
||||
addbyte(0x66); /*ADDW host_reg, imm*/
|
||||
addbyte(0x81);
|
||||
addbyte(0xC0 | host_reg);
|
||||
addword(imm);
|
||||
}
|
||||
static void ADD_HOST_REG_IMM(int host_reg, uint32_t imm)
|
||||
{
|
||||
addbyte(0x81); /*ADDL host_reg, imm*/
|
||||
addbyte(0xC0 | host_reg);
|
||||
addlong(imm);
|
||||
}
|
||||
|
||||
#define AND_HOST_REG_B AND_HOST_REG_L
|
||||
#define AND_HOST_REG_W AND_HOST_REG_L
|
||||
static void AND_HOST_REG_L(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x21); /*ANDL dst_reg, src_reg*/
|
||||
addbyte(0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
static void AND_HOST_REG_IMM(int host_reg, uint32_t imm)
|
||||
{
|
||||
addbyte(0x81); /*ANDL host_reg, imm*/
|
||||
addbyte(0xE0 | host_reg);
|
||||
addlong(imm);
|
||||
}
|
||||
|
||||
#define OR_HOST_REG_B OR_HOST_REG_L
|
||||
#define OR_HOST_REG_W OR_HOST_REG_L
|
||||
static void OR_HOST_REG_L(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x09); /*ORL dst_reg, src_reg*/
|
||||
addbyte(0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
static void OR_HOST_REG_IMM(int host_reg, uint32_t imm)
|
||||
{
|
||||
addbyte(0x81); /*ORL host_reg, imm*/
|
||||
addbyte(0xC8 | host_reg);
|
||||
addlong(imm);
|
||||
}
|
||||
|
||||
|
||||
static void SUB_HOST_REG_B(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x28); /*SUBB dst_reg, src_reg*/
|
||||
addbyte(0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
static void SUB_HOST_REG_W(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*SUBW dst_reg, src_reg*/
|
||||
addbyte(0x29);
|
||||
addbyte(0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
static void SUB_HOST_REG_L(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x29); /*SUBL dst_reg, src_reg*/
|
||||
addbyte(0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
static void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm)
|
||||
{
|
||||
addbyte(0x80); /*SUBB host_reg, imm*/
|
||||
addbyte(0xE8 | host_reg);
|
||||
addbyte(imm);
|
||||
}
|
||||
static void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm)
|
||||
{
|
||||
addbyte(0x66); /*SUBW host_reg, imm*/
|
||||
addbyte(0x81);
|
||||
addbyte(0xE8 | host_reg);
|
||||
addword(imm);
|
||||
}
|
||||
static void SUB_HOST_REG_IMM(int host_reg, uint32_t imm)
|
||||
{
|
||||
addbyte(0x81); /*SUBL host_reg, imm*/
|
||||
addbyte(0xE8 | host_reg);
|
||||
addlong(imm);
|
||||
}
|
||||
|
||||
#define XOR_HOST_REG_B XOR_HOST_REG_L
|
||||
#define XOR_HOST_REG_W XOR_HOST_REG_L
|
||||
static void XOR_HOST_REG_L(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x31); /*XORL dst_reg, src_reg*/
|
||||
addbyte(0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
static void XOR_HOST_REG_IMM(int host_reg, uint32_t imm)
|
||||
{
|
||||
addbyte(0x81); /*XORL host_reg, imm*/
|
||||
addbyte(0xF0 | host_reg);
|
||||
addlong(imm);
|
||||
}
|
||||
|
||||
static void FLAG_C_CLEAR()
|
||||
{
|
||||
addbyte(0x83); /*ANDL [flags],~1*/
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&flags);
|
||||
addbyte(0xfe);
|
||||
}
|
||||
static void FLAG_C_COPY()
|
||||
{
|
||||
addbyte(0x8a); /*MOVB DL, [flags]*/
|
||||
addbyte(0x05 | (REG_DL << 3));
|
||||
addlong((uint32_t)&flags);
|
||||
addbyte(0x0f); /*SETB DH*/
|
||||
addbyte(0x92);
|
||||
addbyte(0xc0 | REG_DH);
|
||||
addbyte(0x80); /*AND DL, ~1*/
|
||||
addbyte(0xe0 | REG_DL);
|
||||
addbyte(0xfe);
|
||||
addbyte(0x08); /*OR DL, DH*/
|
||||
addbyte(0xc0 | REG_DL | (REG_DH << 3));
|
||||
addbyte(0x88); /*MOVB [flags],DL*/
|
||||
addbyte(0x05 | (REG_DL << 3));
|
||||
addlong((uint32_t)&flags);
|
||||
}
|
||||
84
src/codegen_ops_xchg.h
Normal file
84
src/codegen_ops_xchg.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
#define OP_XCHG_AX_(reg) \
|
||||
static uint32_t ropXCHG_AX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int ax_reg, host_reg; \
|
||||
\
|
||||
ax_reg = LOAD_REG_W(REG_AX); \
|
||||
host_reg = LOAD_REG_W(REG_ ## reg); \
|
||||
STORE_REG_TARGET_W_RELEASE(ax_reg, REG_ ## reg); \
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
|
||||
OP_XCHG_AX_(BX)
|
||||
OP_XCHG_AX_(CX)
|
||||
OP_XCHG_AX_(DX)
|
||||
OP_XCHG_AX_(SI)
|
||||
OP_XCHG_AX_(DI)
|
||||
OP_XCHG_AX_(SP)
|
||||
OP_XCHG_AX_(BP)
|
||||
|
||||
#define OP_XCHG_EAX_(reg) \
|
||||
static uint32_t ropXCHG_EAX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int eax_reg, host_reg; \
|
||||
\
|
||||
eax_reg = LOAD_REG_L(REG_EAX); \
|
||||
host_reg = LOAD_REG_L(REG_ ## reg); \
|
||||
STORE_REG_TARGET_L_RELEASE(eax_reg, REG_ ## reg); \
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, REG_EAX); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
|
||||
OP_XCHG_EAX_(EBX)
|
||||
OP_XCHG_EAX_(ECX)
|
||||
OP_XCHG_EAX_(EDX)
|
||||
OP_XCHG_EAX_(ESI)
|
||||
OP_XCHG_EAX_(EDI)
|
||||
OP_XCHG_EAX_(ESP)
|
||||
OP_XCHG_EAX_(EBP)
|
||||
|
||||
static uint32_t ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int src_reg, dst_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
dst_reg = LOAD_REG_B(fetchdat & 7);
|
||||
src_reg = LOAD_REG_B((fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_B_RELEASE(src_reg, fetchdat & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int src_reg, dst_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
dst_reg = LOAD_REG_W(fetchdat & 7);
|
||||
src_reg = LOAD_REG_W((fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_W_RELEASE(src_reg, fetchdat & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int src_reg, dst_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
dst_reg = LOAD_REG_L(fetchdat & 7);
|
||||
src_reg = LOAD_REG_L((fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_L_RELEASE(src_reg, fetchdat & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
|
@ -7,20 +7,19 @@
|
|||
#include "ibm.h"
|
||||
#include "cpu.h"
|
||||
#include "x86.h"
|
||||
#include "x86_flags.h"
|
||||
#include "x86_ops.h"
|
||||
#include "x87.h"
|
||||
|
||||
#include "codegen.h"
|
||||
#include "codegen_ops.h"
|
||||
#include "codegen_ops_x86.h"
|
||||
|
||||
#include "386_common.h"
|
||||
|
||||
#define BLOCK_EXIT_OFFSET 0x1ff0
|
||||
|
||||
#define CPU_BLOCK_END() cpu_block_end = 1
|
||||
|
||||
|
||||
|
||||
|
||||
int host_reg_mapping[NR_HOST_REGS];
|
||||
codeblock_t *codeblock;
|
||||
codeblock_t **codeblock_hash;
|
||||
|
||||
|
|
@ -33,9 +32,9 @@ page_t *pages;
|
|||
|
||||
uint8_t *codeblock_page_dirty;
|
||||
|
||||
static int block_current = 0;
|
||||
int block_current = 0;
|
||||
static int block_num;
|
||||
static int block_pos;
|
||||
int block_pos;
|
||||
|
||||
int cpu_recomp_flushes, cpu_recomp_flushes_latched;
|
||||
int cpu_recomp_evicted, cpu_recomp_evicted_latched;
|
||||
|
|
@ -51,28 +50,6 @@ static uint32_t last_op32;
|
|||
static x86seg *last_ea_seg;
|
||||
static int last_ssegs;
|
||||
|
||||
static inline void addbyte(uint8_t val)
|
||||
{
|
||||
// pclog("Addbyte %02X at %i %i\n", val, block_pos, cpu_block_end);
|
||||
codeblock[block_current].data[block_pos++] = val;
|
||||
if (block_pos >= 8000)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addlong(uint32_t val)
|
||||
{
|
||||
// pclog("Addlong %08X at %i %i\n", val, block_pos, cpu_block_end);
|
||||
*(uint32_t *)&codeblock[block_current].data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= 8000)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void codegen_init()
|
||||
{
|
||||
int c;
|
||||
|
|
@ -696,6 +673,10 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
|
|||
int over = 0;
|
||||
int pc_off = 0;
|
||||
int test_modrm = 1;
|
||||
int c;
|
||||
|
||||
for (c = 0; c < NR_HOST_REGS; c++)
|
||||
host_reg_mapping[c] = -1;
|
||||
|
||||
codegen_timing_start();
|
||||
|
||||
|
|
@ -819,6 +800,21 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
|
|||
generate_call:
|
||||
codegen_timing_opcode(opcode, fetchdat, op_32);
|
||||
|
||||
if (op_table == x86_dynarec_opcodes && recomp_opcodes[(opcode | op_32) & 0x1ff])
|
||||
{
|
||||
uint32_t new_pc = recomp_opcodes[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block);
|
||||
if (new_pc)
|
||||
{
|
||||
STORE_IMM_ADDR_L((uintptr_t)&pc, new_pc);
|
||||
|
||||
codegen_block_ins++;
|
||||
block->ins++;
|
||||
codegen_endpc = (cs + pc) + 8;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
|
||||
// if (output)
|
||||
// pclog("Generate call at %08X %02X %08X %02X %08X %08X %08X %08X %08X %02X %02X %02X %02X\n", &codeblock[block_current][block_pos], opcode, new_pc, ram[old_pc], EAX, EBX, ECX, EDX, ESI, ram[0x7bd2+6],ram[0x7bd2+7],ram[0x7bd2+8],ram[0x7bd2+9]);
|
||||
|
|
|
|||
|
|
@ -11,3 +11,6 @@ enum
|
|||
{
|
||||
OP_RET = 0xc3
|
||||
};
|
||||
|
||||
#define NR_HOST_REGS 3
|
||||
extern int host_reg_mapping[NR_HOST_REGS];
|
||||
|
|
|
|||
Loading…
Reference in a new issue