From 630592125cbbf384e735c8a81146f6950f2c9955 Mon Sep 17 00:00:00 2001 From: TomW Date: Fri, 16 Jan 2015 21:22:14 +0000 Subject: [PATCH] Added code generation for immediate->register and register versions of MOV, XCHG, ADD, SUB, AND, OR, XOR, TEST, CMP, INC and DEC. --- src/Makefile.mingw | 2 +- src/codegen.h | 34 +++ src/codegen_ops.c | 64 +++++ src/codegen_ops.h | 28 ++ src/codegen_ops_arith.h | 621 ++++++++++++++++++++++++++++++++++++++++ src/codegen_ops_logic.h | 273 ++++++++++++++++++ src/codegen_ops_mov.h | 130 +++++++++ src/codegen_ops_x86.h | 305 ++++++++++++++++++++ src/codegen_ops_xchg.h | 84 ++++++ src/codegen_x86.c | 54 ++-- src/codegen_x86.h | 3 + 11 files changed, 1568 insertions(+), 30 deletions(-) create mode 100644 src/codegen_ops.c create mode 100644 src/codegen_ops.h create mode 100644 src/codegen_ops_arith.h create mode 100644 src/codegen_ops_logic.h create mode 100644 src/codegen_ops_mov.h create mode 100644 src/codegen_ops_x86.h create mode 100644 src/codegen_ops_xchg.h diff --git a/src/Makefile.mingw b/src/Makefile.mingw index 9db8194..3411183 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -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 \ diff --git a/src/codegen.h b/src/codegen.h index 9333c46..b9d24e6 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -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 diff --git a/src/codegen_ops.c b/src/codegen_ops.c new file mode 100644 index 0000000..061dc67 --- /dev/null +++ b/src/codegen_ops.c @@ -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 diff --git a/src/codegen_ops.h b/src/codegen_ops.h new file mode 100644 index 0000000..7f4182a --- /dev/null +++ b/src/codegen_ops.h @@ -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 diff --git a/src/codegen_ops_arith.h b/src/codegen_ops_arith.h new file mode 100644 index 0000000..2e3b0e8 --- /dev/null +++ b/src/codegen_ops_arith.h @@ -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; +} diff --git a/src/codegen_ops_logic.h b/src/codegen_ops_logic.h new file mode 100644 index 0000000..eefc450 --- /dev/null +++ b/src/codegen_ops_logic.h @@ -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; +} + diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h new file mode 100644 index 0000000..afbfe68 --- /dev/null +++ b/src/codegen_ops_mov.h @@ -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; +} diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h new file mode 100644 index 0000000..ced357a --- /dev/null +++ b/src/codegen_ops_x86.h @@ -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); +} diff --git a/src/codegen_ops_xchg.h b/src/codegen_ops_xchg.h new file mode 100644 index 0000000..9dc2dcf --- /dev/null +++ b/src/codegen_ops_xchg.h @@ -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; +} diff --git a/src/codegen_x86.c b/src/codegen_x86.c index f3a3b27..9497c98 100644 --- a/src/codegen_x86.c +++ b/src/codegen_x86.c @@ -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]); diff --git a/src/codegen_x86.h b/src/codegen_x86.h index eb162a2..5a1f44d 100644 --- a/src/codegen_x86.h +++ b/src/codegen_x86.h @@ -11,3 +11,6 @@ enum { OP_RET = 0xc3 }; + +#define NR_HOST_REGS 3 +extern int host_reg_mapping[NR_HOST_REGS];