From ba715706b677da7fd6192fea3f02be68a78b9327 Mon Sep 17 00:00:00 2001 From: TomW Date: Sun, 8 Feb 2015 17:17:14 +0000 Subject: [PATCH] Added code generation for memory versions of MOV, and memory source versions of ADD, SUB, AND, OR, XOR and CMP. --- src/386_dynarec.c | 4 +- src/codegen.h | 14 +- src/codegen_ops.c | 4 +- src/codegen_ops_arith.h | 39 ++- src/codegen_ops_mov.h | 309 ++++++++++++++++---- src/codegen_ops_x86.h | 633 +++++++++++++++++++++++++++++++++++++++- src/codegen_x86.c | 65 ++++- src/codegen_x86.h | 3 + src/pc.c | 2 + src/win-status.c | 8 +- src/x86.h | 1 + 11 files changed, 997 insertions(+), 85 deletions(-) diff --git a/src/386_dynarec.c b/src/386_dynarec.c index c26a7ab..ff9f7f6 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -21,8 +21,8 @@ int cpu_reps, cpu_reps_latched; int cpu_notreps, cpu_notreps_latched; int inrecomp = 0; -int cpu_recomp_blocks, cpu_recomp_ins, cpu_new_blocks; -int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_new_blocks_latched; +int cpu_recomp_blocks, cpu_recomp_ins, cpu_recomp_full_ins, cpu_new_blocks; +int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched; int cpu_block_end = 0; diff --git a/src/codegen.h b/src/codegen.h index f292ef6..ff7cf7b 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -71,8 +71,8 @@ void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr) extern int cpu_block_end; -extern int cpu_recomp_blocks, cpu_recomp_ins, cpu_new_blocks; -extern int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_new_blocks_latched; +extern int cpu_recomp_blocks, cpu_recomp_ins, cpu_recomp_full_ins, cpu_new_blocks; +extern int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched; extern int cpu_recomp_flushes, cpu_recomp_flushes_latched; extern int cpu_recomp_evicted, cpu_recomp_evicted_latched; extern int cpu_recomp_reuse, cpu_recomp_reuse_latched; @@ -111,7 +111,7 @@ extern int block_pos; static inline void addbyte(uint8_t val) { codeblock[block_current].data[block_pos++] = val; - if (block_pos >= 1850) + if (block_pos >= 1800) { CPU_BLOCK_END(); } @@ -121,7 +121,7 @@ static inline void addword(uint16_t val) { *(uint16_t *)&codeblock[block_current].data[block_pos] = val; block_pos += 2; - if (block_pos >= 1850) + if (block_pos >= 1800) { CPU_BLOCK_END(); } @@ -131,7 +131,7 @@ static inline void addlong(uint32_t val) { *(uint32_t *)&codeblock[block_current].data[block_pos] = val; block_pos += 4; - if (block_pos >= 1850) + if (block_pos >= 1800) { CPU_BLOCK_END(); } @@ -139,4 +139,8 @@ static inline void addlong(uint32_t val) /*Current physical page of block being recompiled. -1 if no recompilation taking place */ extern uint32_t recomp_page; + +extern x86seg *op_ea_seg; +extern int op_ssegs; +extern uint32_t op_old_pc; #endif diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 061dc67..f1e3388 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -30,7 +30,7 @@ RecompOpFn recomp_opcodes[512] = /*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, +/*a0*/ ropMOV_AL_a, ropMOV_AX_a, ropMOV_a_AL, ropMOV_a_AX, 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, @@ -52,7 +52,7 @@ RecompOpFn recomp_opcodes[512] = /*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, +/*a0*/ ropMOV_AL_a, ropMOV_EAX_a, ropMOV_a_AL, ropMOV_a_EAX, 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, diff --git a/src/codegen_ops_arith.h b/src/codegen_ops_arith.h index 152e6ad..b12be70 100644 --- a/src/codegen_ops_arith.h +++ b/src/codegen_ops_arith.h @@ -134,12 +134,19 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin { \ int src_reg, dst_reg; \ \ - if ((fetchdat & 0xc0) != 0xc0) \ - return 0; \ + if ((fetchdat & 0xc0) == 0xc0) \ + { \ + src_reg = LOAD_REG_B(fetchdat & 7); \ + } \ + else \ + { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + MEM_LOAD_ADDR_EA_B(target_seg); \ + src_reg = 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); \ @@ -154,12 +161,19 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin { \ int src_reg, dst_reg; \ \ - if ((fetchdat & 0xc0) != 0xc0) \ - return 0; \ + if ((fetchdat & 0xc0) == 0xc0) \ + { \ + src_reg = LOAD_REG_W(fetchdat & 7); \ + } \ + else \ + { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + MEM_LOAD_ADDR_EA_W(target_seg); \ + src_reg = 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); \ @@ -174,12 +188,19 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin { \ int src_reg, dst_reg; \ \ - if ((fetchdat & 0xc0) != 0xc0) \ - return 0; \ + if ((fetchdat & 0xc0) == 0xc0) \ + { \ + src_reg = LOAD_REG_L(fetchdat & 7); \ + } \ + else \ + { \ + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \ + MEM_LOAD_ADDR_EA_L(target_seg); \ + src_reg = 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); \ diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h index afbfe68..1af0a1c 100644 --- a/src/codegen_ops_mov.h +++ b/src/codegen_ops_mov.h @@ -22,109 +22,318 @@ static uint32_t ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, 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; + int host_reg = LOAD_REG_B((fetchdat >> 3) & 7); - if ((fetchdat & 0xc0) != 0xc0) - return 0; - - host_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_REG_TARGET_B_RELEASE(host_reg, fetchdat & 7); + if ((fetchdat & 0xc0) == 0xc0) + { + STORE_REG_TARGET_B_RELEASE(host_reg, fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 0); + + MEM_STORE_ADDR_EA_B(target_seg, host_reg); + RELEASE_REG(host_reg); + } 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; + int host_reg = LOAD_REG_W((fetchdat >> 3) & 7); - host_reg = LOAD_REG_W((fetchdat >> 3) & 7); - STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); + if ((fetchdat & 0xc0) == 0xc0) + { + STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 1); + + MEM_STORE_ADDR_EA_W(target_seg, host_reg); + RELEASE_REG(host_reg); + } 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); + if ((fetchdat & 0xc0) == 0xc0) + { + STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + + CHECK_SEG_WRITE(target_seg); + CHECK_SEG_LIMITS(target_seg, 3); + + MEM_STORE_ADDR_EA_L(target_seg, host_reg); + RELEASE_REG(host_reg); + + } + 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) + { + int host_reg = LOAD_REG_B(fetchdat & 7); + STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - if ((fetchdat & 0xc0) != 0xc0) - return 0; - - host_reg = LOAD_REG_B(fetchdat & 7); - STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_B(target_seg); + STORE_REG_TARGET_B_RELEASE(0, (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) + { + int host_reg = LOAD_REG_W(fetchdat & 7); + STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); - if ((fetchdat & 0xc0) != 0xc0) - return 0; - - host_reg = LOAD_REG_W(fetchdat & 7); - STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_W(target_seg); + STORE_REG_TARGET_W_RELEASE(0, (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); + if ((fetchdat & 0xc0) == 0xc0) + { + int host_reg = LOAD_REG_L(fetchdat & 7); + STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + + CHECK_SEG_READ(target_seg); + + MEM_LOAD_ADDR_EA_L(target_seg); + STORE_REG_TARGET_L_RELEASE(0, (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) + { + STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff); + } + else + { +// return 0; + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + uint32_t imm = fastreadb(cs + op_pc + 1); + int host_reg = LOAD_REG_IMM(imm); - if ((fetchdat & 0xc0) != 0xc0) - return 0; + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + CHECK_SEG_WRITE(target_seg); + + MEM_STORE_ADDR_EA_B(target_seg, host_reg); + RELEASE_REG(host_reg); + } - 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) + { + STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff); + } + else + { +// if ((cs+pc) <= 0xbff70000 || (cs+pc) > 0xbff80000) +// return 0; +// { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + uint32_t imm = fastreadw(cs + op_pc + 1); + int host_reg = LOAD_REG_IMM(imm); +//pclog("MOV imm %04x(%08x):%08x %08x %04x\n", CS, cs, pc, op_pc, imm); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + CHECK_SEG_WRITE(target_seg); - if ((fetchdat & 0xc0) != 0xc0) - return 0; + MEM_STORE_ADDR_EA_W(target_seg, host_reg); + RELEASE_REG(host_reg); +// } + } - 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) + { + uint32_t imm = fastreadl(cs + op_pc + 1); - if ((fetchdat & 0xc0) != 0xc0) - return 0; + STORE_IMM_REG_L(fetchdat & 7, imm); + } + else + { +// return 0; + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + uint32_t imm = fastreadl(cs + op_pc + 1); + int host_reg = LOAD_REG_IMM(imm); - STORE_IMM_REG_L(fetchdat & 7, imm); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + CHECK_SEG_WRITE(target_seg); + + MEM_STORE_ADDR_EA_L(target_seg, host_reg); + RELEASE_REG(host_reg); + } return op_pc + 5; } + + +static uint32_t ropMOV_AL_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_READ(op_ea_seg); + + MEM_LOAD_ADDR_IMM_B(op_ea_seg, addr); + STORE_REG_TARGET_B_RELEASE(0, REG_AL); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t ropMOV_AX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_READ(op_ea_seg); + + MEM_LOAD_ADDR_IMM_W(op_ea_seg, addr); + STORE_REG_TARGET_W_RELEASE(0, REG_AX); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t ropMOV_EAX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_READ(op_ea_seg); + + MEM_LOAD_ADDR_IMM_L(op_ea_seg, addr); + STORE_REG_TARGET_L_RELEASE(0, REG_EAX); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} + +static uint32_t ropMOV_a_AL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + int host_reg; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_WRITE(op_ea_seg); + + host_reg = LOAD_REG_B(REG_AL); + + MEM_STORE_ADDR_IMM_B(op_ea_seg, addr, host_reg); + RELEASE_REG(host_reg); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t ropMOV_a_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + int host_reg; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_WRITE(op_ea_seg); + + host_reg = LOAD_REG_W(REG_AX); + + MEM_STORE_ADDR_IMM_W(op_ea_seg, addr, host_reg); + RELEASE_REG(host_reg); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} +static uint32_t ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + uint32_t addr; + int host_reg; + + if (op_32 & 0x200) + addr = fastreadl(cs + op_pc); + else + addr = fastreadw(cs + op_pc); + + CHECK_SEG_WRITE(op_ea_seg); + + host_reg = LOAD_REG_L(REG_EAX); + + MEM_STORE_ADDR_IMM_L(op_ea_seg, addr, host_reg); + RELEASE_REG(host_reg); + + return op_pc + ((op_32 & 0x200) ? 4 : 2); +} diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h index 37cf36e..fff7264 100644 --- a/src/codegen_ops_x86.h +++ b/src/codegen_ops_x86.h @@ -1,7 +1,14 @@ +/*Register allocation : + EBX, ECX, EDX - emulated registers + EAX - work register, EA storage + ESI, EDI - work registers +*/ +#define HOST_REG_START 1 +#define HOST_REG_END 4 static inline int find_host_reg() { int c; - for (c = 0; c < NR_HOST_REGS; c++) + for (c = HOST_REG_START; c < HOST_REG_END; c++) { if (host_reg_mapping[c] == -1) break; @@ -100,6 +107,18 @@ static int LOAD_REG_L(int reg) return host_reg; } +static int LOAD_REG_IMM(uint32_t imm) +{ + int host_reg = find_host_reg(); + host_reg_mapping[host_reg] = reg; + + addbyte(0xc7); /*MOVL host_reg, imm*/ + addbyte(0xc0 | host_reg); + addlong(imm); + + return host_reg; +} + static void STORE_REG_B_RELEASE(int host_reg) { addbyte(0x88); /*MOVB [reg],host_reg*/ @@ -284,3 +303,615 @@ static void CALL_FUNC(void *dest) addbyte(0xE8); /*CALL*/ addlong(((uint8_t *)dest - (uint8_t *)(&codeblock[block_current].data[block_pos + 4]))); } + + + + +static void CHECK_SEG_READ(x86seg *seg) +{ + addbyte(0x83); /*CMP seg->base, -1*/ + addbyte(0x05|0x38); + addlong((uint32_t)&seg->base); + addbyte(-1); + addbyte(0x0f); + addbyte(0x84); /*JE end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} +static void CHECK_SEG_WRITE(x86seg *seg) +{ + addbyte(0x83); /*CMP seg->base, -1*/ + addbyte(0x05|0x38); + addlong((uint32_t)&seg->base); + addbyte(-1); + addbyte(0x0f); + addbyte(0x84); /*JE end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} +static void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) +{ + addbyte(0x3b); /*CMP EAX, seg->limit_low*/ + addbyte(0x05); + addlong((uint32_t)&seg->limit_low); + addbyte(0x0f); /*JB BLOCK_GPF_OFFSET*/ + addbyte(0x82); + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + if (end_offset) + { + addbyte(0x83); /*ADD EAX, end_offset*/ + addbyte(0xc0); + addbyte(end_offset); + addbyte(0x3b); /*CMP EAX, seg->limit_high*/ + addbyte(0x05); + addlong((uint32_t)&seg->limit_high); + addbyte(0x0f); /*JNBE BLOCK_GPF_OFFSET*/ + addbyte(0x87); + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + addbyte(0x83); /*SUB EAX, end_offset*/ + addbyte(0xe8); + addbyte(end_offset); + } +} + +static void MEM_LOAD_ADDR_EA_B(x86seg *seg) +{ + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t)&seg->base); + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t)readlookup2); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3+2); + addbyte(0x8a); /*MOV AL, [EDX+EDI]*/ + addbyte(0x04); + addbyte(0x3a); + addbyte(0xeb); /*JMP done*/ + addbyte(4+3+5+7+6); + addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x04); + addbyte(0x89); /*MOV [ESP], ESI*/ + addbyte(0x34); + addbyte(0x24); + addbyte(0xe8); /*CALL readmemb386l*/ + addlong((uint32_t)readmemb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3d); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ + addbyte(0x0f); /*MOVZX EAX, AL*/ + addbyte(0xb6); + addbyte(0xc0); + host_reg_mapping[0] = 8; +} +static void MEM_LOAD_ADDR_EA_W(x86seg *seg) +{ + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t)&seg->base); + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0x83); /*XOR EDI, -1*/ + addbyte(0xf7); + addbyte(-1); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 0xfff*/ + addbyte(0xc7); + addlong(0xfff); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t)readlookup2); + addbyte(0x74); /*JE slowpath*/ + addbyte(3+3+2+4+2); + addbyte(0x83); /*XOR EDI, -1*/ + addbyte(0xf7); + addbyte(-1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4+2); + addbyte(0x66); /*MOV AX, [EDX+EDI]*/ + addbyte(0x8b); + addbyte(0x04); + addbyte(0x3a); + addbyte(0xeb); /*JMP done*/ + addbyte(4+3+5+7+6); + addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x04); + addbyte(0x89); /*MOV [ESP], ESI*/ + addbyte(0x34); + addbyte(0x24); + addbyte(0xe8); /*CALL readmemwl*/ + addlong((uint32_t)readmemwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3d); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); + addbyte(0x85); /*JNE end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ + addbyte(0x0f); /*MOVZX EAX, AX*/ + addbyte(0xb7); + addbyte(0xc0); + host_reg_mapping[0] = 8; +} +static void MEM_LOAD_ADDR_EA_L(x86seg *seg) +{ + addbyte(0x8b); /*MOVL EDX, seg->base*/ + addbyte(0x05 | (REG_EDX << 3)); + addlong((uint32_t)&seg->base); + addbyte(0x89); /*MOV ESI, EDX*/ + addbyte(0xd6); + addbyte(0x01); /*ADDL EDX, EAX*/ + addbyte(0xc2); + addbyte(0x89); /*MOV EDI, EDX*/ + addbyte(0xd7); + addbyte(0x83); /*XOR EDI, -1*/ + addbyte(0xf7); + addbyte(-1); + addbyte(0xc1); /*SHR EDX, 12*/ + addbyte(0xea); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 0xffc*/ + addbyte(0xc7); + addlong(0xffc); + addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/ + addbyte(0x14); + addbyte(0x95); + addlong((uint32_t)readlookup2); + addbyte(0x74); /*JE slowpath*/ + addbyte(3+3+2+3+2); + addbyte(0x83); /*XOR EDI, -1*/ + addbyte(0xf7); + addbyte(-1); + addbyte(0x83); /*CMP EDX, -1*/ + addbyte(0xfa); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3+2); + addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/ + addbyte(0x04); + addbyte(0x3a); + addbyte(0xeb); /*JMP done*/ + addbyte(4+3+5+7+6); + addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x04); + addbyte(0x89); /*MOV [ESP], ESI*/ + addbyte(0x34); + addbyte(0x24); + addbyte(0xe8); /*CALL readmemll*/ + addlong((uint32_t)readmemll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3d); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); + addbyte(0x85); /*JNE end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ + host_reg_mapping[0] = 8; +} + +static void MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_B(seg); +} +static void MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_W(seg); +} +static void MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_L(seg); +} + +static void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) +{ + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t)&seg->base); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 0xfff*/ + addbyte(0xc7); + addlong(0xfff); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t)writelookup2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3+2); + addbyte(0x88); /*MOV [EDI+ESI],host_reg*/ + addbyte(0x04 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xeb); /*JMP done*/ + addbyte(4+5+4+3+5+7+6); + addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x04); + addbyte(0xa1); /*MOV EAX, seg->base*/ + addlong((uint32_t)&seg->base); + addbyte(0x89); /*MOV [ESP+8], host_reg*/ + addbyte(0x44 | (host_reg << 3)); + addbyte(0x24); + addbyte(0x08); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xe8); /*CALL writememb386l*/ + addlong((uint32_t)writememb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3d); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) +{ + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t)&seg->base); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); + addbyte(0x83); /*XOR EDI, -1*/ + addbyte(0xf7); + addbyte(-1); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 0xfff*/ + addbyte(0xc7); + addlong(0xfff); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t)writelookup2); + addbyte(0x74); /*JE slowpath*/ + addbyte(3+3+2+4+2); + addbyte(0x83); /*XOR EDI, -1*/ + addbyte(0xf7); + addbyte(-1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4+2); + addbyte(0x66); /*MOV [EDI+ESI],host_reg*/ + addbyte(0x89); + addbyte(0x04 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xeb); /*JMP done*/ + addbyte(4+5+4+3+5+7+6); + addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x04); + addbyte(0xa1); /*MOV EAX, seg->base*/ + addlong((uint32_t)&seg->base); + addbyte(0x89); /*MOV [ESP+8], host_reg*/ + addbyte(0x44 | (host_reg << 3)); + addbyte(0x24); + addbyte(0x08); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xe8); /*CALL writememwl*/ + addlong((uint32_t)writememwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3d); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) +{ + addbyte(0x8b); /*MOVL ESI, seg->base*/ + addbyte(0x05 | (REG_ESI << 3)); + addlong((uint32_t)&seg->base); + addbyte(0x01); /*ADDL ESI, EAX*/ + addbyte(0xc0 | (REG_EAX << 3) | REG_ESI); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xc0 | (REG_ESI << 3) | REG_EDI); + addbyte(0x83); /*XOR EDI, -1*/ + addbyte(0xf7); + addbyte(-1); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 0xffc*/ + addbyte(0xc7); + addlong(0xffc); + addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/ + addbyte(0x04 | (REG_ESI << 3)); + addbyte(0x85 | (REG_ESI << 3)); + addlong((uint32_t)writelookup2); + addbyte(0x74); /*JE slowpath*/ + addbyte(3+3+2+3+2); + addbyte(0x83); /*XOR EDI, -1*/ + addbyte(0xf7); + addbyte(-1); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3+2); + addbyte(0x89); /*MOV [EDI+ESI],host_reg*/ + addbyte(0x04 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xeb); /*JMP done*/ + addbyte(4+5+4+3+5+7+6); + addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x04); + addbyte(0xa1); /*MOV EAX, seg->base*/ + addlong((uint32_t)&seg->base); + addbyte(0x89); /*MOV [ESP+8], host_reg*/ + addbyte(0x44 | (host_reg << 3)); + addbyte(0x24); + addbyte(0x08); + addbyte(0x89); /*MOV [ESP], EAX*/ + addbyte(0x04); + addbyte(0x24); + addbyte(0xe8); /*CALL writememll*/ + addlong((uint32_t)writememll - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3d); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} + +static void MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_B(seg, host_reg); +} +static void MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_L(seg, host_reg); +} +static void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_W(seg, host_reg); +} + + +static x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +{ + int mod = (fetchdat >> 6) & 3; + int reg = (fetchdat >> 3) & 7; + int rm = fetchdat & 7; + if (!mod && rm == 6) + { + addbyte(0xb8); /*MOVL EAX, imm16*/ + addlong((fetchdat >> 8) & 0xffff); + (*op_pc) += 2; + } + else + { + switch (mod) + { + case 0: + addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/ + addlong((uint32_t)mod1add[0][rm]); + addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ + addbyte(0x05); + addlong((uint32_t)mod1add[1][rm]); + break; + case 1: + addbyte(0xb8); /*MOVL EAX, imm8*/ + addlong((uint32_t)(int8_t)(rmdat >> 8));// pc++; + addbyte(0x03); /*ADDL EAX, *mod1add[0][rm]*/ + addbyte(0x05); + addlong((uint32_t)mod1add[0][rm]); + addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/ + addbyte(0x05); + addlong((uint32_t)mod1add[1][rm]); + (*op_pc)++; + break; + case 2: + addbyte(0xb8); /*MOVL EAX, imm16*/ + addlong((fetchdat >> 8) & 0xffff);// pc++; + addbyte(0x03); /*EAX, ADDL *mod1add[0][rm]*/ + addbyte(0x05); + addlong((uint32_t)mod1add[0][rm]); + addbyte(0x03); /*EAX, ADDL *mod1add[1][rm]*/ + addbyte(0x05); + addlong((uint32_t)mod1add[1][rm]); + (*op_pc) += 2; + break; + } + addbyte(0x25); /*ANDL EAX, 0xffff*/ + addlong(0xffff); + + if (mod1seg[rm] == &ss && !op_ssegs) + op_ea_seg = &_ss; + } + return op_ea_seg; +} + +static x86seg *FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +{ + uint32_t new_eaaddr; + int mod = (fetchdat >> 6) & 3; + int reg = (fetchdat >> 3) & 7; + int rm = fetchdat & 7; + + if (rm == 4) + { + uint8_t sib = fetchdat >> 8; + (*op_pc)++; + + switch (mod) + { + case 0: + if ((sib & 7) == 5) + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL EAX, imm32*/ + addlong(new_eaaddr);// pc++; + (*op_pc) += 4; + } + else + { + addbyte(0xa1); /*MOVL EAX, regs[sib&7].l*/ + addlong((uint32_t)®s[sib & 7].l); + } + break; + case 1: + new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff); + addbyte(0xb8); /*MOVL EAX, imm8*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ + addbyte(0x05); + addlong((uint32_t)®s[sib & 7].l); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL EAX, new_eaaddr*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ + addbyte(0x05); + addlong((uint32_t)®s[sib & 7].l); + (*op_pc) += 4; + break; + } + if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ + { + addbyte(0x05); /*ADDL EAX, stack_offset*/ + addlong(stack_offset); + } + if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &_ss; + if (((sib >> 3) & 7) != 4) + { + switch (sib >> 6) + { + case 0: + addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/ + addbyte(0x05); + addlong((uint32_t)®s[(sib >> 3) & 7].l); + break; + case 1: + addbyte(0x8B); addbyte(0x05 | (REG_EDI << 3)); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL EDI, reg*/ + addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + break; + case 2: + addbyte(0x8B); addbyte(0x05 | (REG_EDI << 3)); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL EDI, reg*/ + addbyte(0xC1); addbyte(0xE0 | REG_EDI); addbyte(2); /*SHL EDI, 2*/ + addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + break; + case 3: + addbyte(0x8B); addbyte(0x05 | (REG_EDI << 3)); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL EDI reg*/ + addbyte(0xC1); addbyte(0xE0 | REG_EDI); addbyte(3); /*SHL EDI, 3*/ + addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/ + break; + } + } + } + else + { + if (!mod && rm == 5) + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL EAX, imm32*/ + addlong(new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; + } + addbyte(0xa1); /*MOVL EAX, regs[rm].l*/ + addlong((uint32_t)®s[rm].l); + eaaddr = regs[rm].l; + if (mod) + { + if (rm == 5 && !op_ssegs) + op_ea_seg = &_ss; + if (mod == 1) + { + addbyte(0x05); /*ADD EAX, imm8*/ + addlong((uint32_t)(int8_t)(fetchdat >> 8)); + (*op_pc)++; + } + else + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x05); /*ADD EAX, imm32*/ + addlong(new_eaaddr); + (*op_pc) += 4; + } + } + } + return op_ea_seg; +} + +static x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) +{ + if (op_32 & 0x200) + return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0); + return FETCH_EA_16(op_ea_seg, fetchdat, op_ssegs, op_pc); +} diff --git a/src/codegen_x86.c b/src/codegen_x86.c index 55ce35f..1fc44e2 100644 --- a/src/codegen_x86.c +++ b/src/codegen_x86.c @@ -10,13 +10,15 @@ #include "x87.h" #include "mem.h" +#include "386_common.h" + #include "codegen.h" #include "codegen_ops.h" #include "codegen_ops_x86.h" -#include "386_common.h" - -#define BLOCK_EXIT_OFFSET 0x7f0 +x86seg *op_ea_seg; +int op_ssegs; +uint32_t op_old_pc; uint32_t recomp_page = -1; @@ -38,6 +40,7 @@ static uint32_t codegen_endpc; int codegen_block_cycles; static int codegen_block_ins; +static int codegen_block_full_ins; static uint32_t last_op32; static x86seg *last_ea_seg; @@ -188,17 +191,28 @@ void codegen_block_init(uint32_t phys_addr) block->use32 = use32; block->next = block->prev = NULL; - block_pos = 0; + block_pos = BLOCK_GPF_OFFSET; + addbyte(0xc7); /*MOV [ESP],0*/ + addbyte(0x04); + addbyte(0x24); + addlong(0); + addbyte(0xc7); /*MOV [ESP+4],0*/ + addbyte(0x44); + addbyte(0x24); + addbyte(0x04); + addlong(0); + addbyte(0xe8); /*CALL x86gpf*/ + addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4])); block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/ - addbyte(0x83); /*ADDL $8,%esp*/ + addbyte(0x83); /*ADDL $16,%esp*/ addbyte(0xC4); - addbyte(0x08); + addbyte(0x10); addbyte(0xC3); /*RET*/ cpu_block_end = 0; block_pos = 0; /*Entry code*/ - addbyte(0x83); /*SUBL $8,%esp*/ + addbyte(0x83); /*SUBL $16,%esp*/ addbyte(0xEC); - addbyte(0x08); + addbyte(0x10); // pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num); @@ -210,6 +224,7 @@ void codegen_block_init(uint32_t phys_addr) codegen_timing_block_start(); codegen_block_ins = 0; + codegen_block_full_ins = 0; recomp_page = phys_addr & ~0xfff; } @@ -342,11 +357,22 @@ void codegen_block_end() addlong((uint32_t)&cpu_recomp_ins); addlong(codegen_block_ins); } - - addbyte(0x83); /*ADDL $8,%esp*/ +#if 0 + if (codegen_block_full_ins) + { + addbyte(0x81); /*ADD $codegen_block_ins,ins*/ + addbyte(0x05); + addlong((uint32_t)&cpu_recomp_full_ins); + addlong(codegen_block_full_ins); + } +#endif + addbyte(0x83); /*ADDL $16,%esp*/ addbyte(0xC4); - addbyte(0x08); + addbyte(0x10); addbyte(0xC3); /*RET*/ + + if (block_pos > BLOCK_GPF_OFFSET) + fatal("Over limit!\n"); // pclog("End block %i\n", block_num); recomp_page = -1; @@ -636,8 +662,6 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t uint32_t op_32 = use32; uint32_t op_pc = new_pc; OpFn *op_table = x86_dynarec_opcodes; - x86seg *op_ea_seg = &_ds; - int op_ssegs = 0; int opcode_shift = 0; int opcode_mask = 0x3ff; int over = 0; @@ -645,6 +669,10 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t int test_modrm = 1; int c; + op_ea_seg = &_ds; + op_ssegs = 0; + op_old_pc = old_pc; + for (c = 0; c < NR_HOST_REGS; c++) host_reg_mapping[c] = -1; @@ -779,6 +807,7 @@ generate_call: codegen_block_ins++; block->ins++; + codegen_block_full_ins++; codegen_endpc = (cs + pc) + 8; return; @@ -899,6 +928,16 @@ generate_call: addlong(codegen_block_ins); codegen_block_ins = 0; } +#if 0 + if (codegen_block_full_ins) + { + addbyte(0x81); /*ADD $codegen_block_ins,ins*/ + addbyte(0x05); + addlong((uint32_t)&cpu_recomp_full_ins); + addlong(codegen_block_full_ins); + codegen_block_full_ins = 0; + } +#endif } block->ins++; diff --git a/src/codegen_x86.h b/src/codegen_x86.h index 5a1f44d..8567979 100644 --- a/src/codegen_x86.h +++ b/src/codegen_x86.h @@ -7,6 +7,9 @@ #define HASH(l) ((l) & 0x1ffff) +#define BLOCK_EXIT_OFFSET 0x7f0 +#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) + enum { OP_RET = 0xc3 diff --git a/src/pc.c b/src/pc.c index 3bd1aa2..b033e3b 100644 --- a/src/pc.c +++ b/src/pc.c @@ -372,6 +372,7 @@ void runpc() #if DYNAREC cpu_recomp_blocks_latched = cpu_recomp_blocks; cpu_recomp_ins_latched = cpu_recomp_ins; + cpu_recomp_full_ins_latched = cpu_recomp_full_ins; cpu_new_blocks_latched = cpu_new_blocks; cpu_recomp_flushes_latched = cpu_recomp_flushes; cpu_recomp_evicted_latched = cpu_recomp_evicted; @@ -382,6 +383,7 @@ void runpc() cpu_recomp_blocks = 0; cpu_recomp_ins = 0; + cpu_recomp_full_ins = 0; cpu_new_blocks = 0; cpu_recomp_flushes = 0; cpu_recomp_evicted = 0; diff --git a/src/win-status.c b/src/win-status.c index 9dbd6a4..a040bb9 100644 --- a/src/win-status.c +++ b/src/win-status.c @@ -48,7 +48,8 @@ static BOOL CALLBACK status_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR "CPU time : %f%% (%f%%)\n" #ifdef DYNAREC "New blocks : %i\nOld blocks : %i\nRecompiled speed : %f MIPS\nAverage size : %f\n" - "Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS\nREP : %i\nnot REP : %i\n" + "Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS" +// "\nFully recompiled ins %% : %f%%" #endif ,mips, flops, @@ -67,8 +68,9 @@ static BOOL CALLBACK status_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR cpu_recomp_flushes_latched, cpu_recomp_evicted_latched, cpu_recomp_reuse_latched, cpu_recomp_removed_latched, - ((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq), - cpu_reps_latched, cpu_notreps_latched + ((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq) +// ((double)cpu_recomp_full_ins_latched / (double)cpu_recomp_ins_latched) * 100.0 +// cpu_reps_latched, cpu_notreps_latched #endif ); main_time = 0; diff --git a/src/x86.h b/src/x86.h index 3d1d851..601201e 100644 --- a/src/x86.h +++ b/src/x86.h @@ -101,3 +101,4 @@ extern int inscounts[256]; void x86illegal(); void x86seg_reset(); +void x86gpf(char *s, uint16_t error);